Skip to content

Other Videos is its own library type: pill, Library and Sources (#599) - #1033

Draft
Bardioc1977 wants to merge 20 commits into
GLinnik21:mainfrom
Bardioc1977:fix-599-other-videos
Draft

Bardioc1977 wants to merge 20 commits into
GLinnik21:mainfrom
Bardioc1977:fix-599-other-videos

Conversation

@Bardioc1977

Copy link
Copy Markdown

#1029 (ru catalogue keys) is on main; this branch has origin/main merged in (signed-off merge commit) and every gate below ran on the committed tree.

What

A Plex "Other Videos" library (type movie, agent tv.plex.agents.none, scanner Plex Video Files) is no longer folded
into Movies. It gets its own Other Videos pill after TV Shows, its own Library page (grid, A-Z rail, Sort & Filter with
Plays, Recommended, Collections), its own Sources list and its own Favorite-libraries switch. Switching the library off
removes only that pill. The pill reads the library's own name when it is the only Other Videos library you follow, and
the translated "Other Videos" otherwise.

Why

The app classified a section by its Plex type alone, so Other Videos (type movie) was a Movies library. agent and
scanner are in the same plain /library/sections answer.

How

  • LibrarySection reads agent and scanner; is_other_videos() = movie AND a "none" agent AND a scanner starting with
    Plex Video Files (case-insensitive; the legacy com.plexapp.agents.none / Plex Video Files Scanner too). A curated
    Movies library (Movie scanner), a Movie agent with the Video Files scanner, and a server that sends neither field all
    stay Movies: a false negative is today's behaviour, a false positive would move a curated library off its pill.
  • SecKind::Video (app code "video": additive in last_library, rollback-safe; Movie 0 / Show 1 keep their canon
    codes, so SCREEN_SHAPES_PIN and the replay anchors do not move).
  • One HomeTab <-> strip key <-> section kind mapping replaces six hand-written copies; Search and Watchlist ended
    theirs in a silent fallthrough and would not have pressed a new pill. Strip keys are declared by one strip_keys!
    macro with a compile-time pairwise-distinct assert; TAB_KEY_VIDEOS = STRIP_BASE + 7 (open Live TV: watch the server's channels, and a TV tab of channel covers #993 holds +6).
  • Home follows the server's visibility: a library the owner hid from the home screen (hidden 1 or 2, verified values)
    sends no Home row, so its pill is the way in; a visible one (hidden 0) gets its home.videos.recent row (a hub of
    type clip whose items are movie rows). Personal-video hubs (home.videos.*, video.*) never feed the recently-added families' hero allowance and pool (one predicate in both places that spend it; an in-progress clip still reaches the hero through Continue Watching).
  • The pill's label is the library's own server title when exactly one favourite Other Videos library exists
    (DirectoryView::tab_library_title, one rule, sole_favorite_title, shared by the table and the view). The title is server text,
    never translated: control characters become spaces, characters that draw nothing (zero-width, bidi, soft hyphen, BOM) are
    dropped, white space collapses, at most 128 characters are kept, and it is elided by character to the room the strip leaves
    (widgets::fit_title_face: 904 px of strip content keeps the unfurled profile chip its pinned 290 px, so the text budget is
    240 px (en de es fr it pt), 209 (hu), 202 (ru), 189 (be); below a 60 px floor the translated word is used). Two or more favourite
    libraries, an empty or control-only title, or a title equal to another pill's label (Unicode lowercase, so ФИЛЬМЫ is
    Фильмы) keep the translated word. Movies and TV Shows keep their type words, and so do the Type menu and the counts.
    tabs_gen moves when the title does (BrowseState::tab_titles, stamped beside the pill mask), and append_sections_with now
    takes a new title for a section it already holds (a blank rename is ignored), so a server rename shows after the next
    rediscovery (restart, profile or server switch, Sources "Re-check"; nothing polls). A library deleted on the server stays until
    restart, as before.
  • A friend's Other Videos library stays Off in Favorite libraries by default (household_type is true for Video), so a
    friend's personal clips never reach a household's Home unasked; the household's own is On.
  • i18n: four keys in all nine locales. Mock PMS: opt-in --other-videos N (+ --other-videos-hidden, --other-videos-title NAME,
    --other-videos-sections K, and POST /_mock/config {"section_titles": {...}} to stage a rename), default off.

Verified

Real PMS 1.43.5 (GET only, read-only): section fields (agent, scanner, hidden), hub types and ids, the hidden
values 0/1/2 via the library's prefs, listing / sort (incl. viewCount) / collections.

Red then green (details: commit messages): C4 a_three_section_answer_projects_movies_shows_and_other_videos
((3, "Other Videos", Movie) vs Video), C6 the clip-hub tests (hub count 0 vs 1; hero allowance 5 vs 8; with only the
hub gate opened the hero pool was ["901","902","1"], with the predicate ["1"]).

Gates on the committed tree (clean git status, origin/main merged in):
make check-cargo exit 0 (test result: ok. 1073 passed app default features, 1186 passed app hostsim, plx_data 1279, plx_ui 1406,
plx_screens 1720, plx_plex 738, plx_platform 288, plx_appkit 347, plx_media 1744/1906 default/hostsim; 0 failed), make check-python-harness
exit 0, make check-nodef, make lint, ci/check-deps.sh (ledgers unchanged: blocking 2, workers 9, globals 66, forks 58, fxlanes 11),
module layers, list caps, localization, language lists, python3 tests/test_mock_pms_library.py (103 tests, OK),
tests/replay_fixtures.py against the hostsim build (3 fixtures, 6 replays, 0 failures, verdict=SAME; no replay anchor or SCREEN_SHAPES_PIN moved).
make check as a whole stops at ci/test_disk_preflight.py (free disk space of the machine it ran on; unrelated).

Red then green for the pill title: the ten other_videos_pill tests (e.g. left: "Other Videos" vs right: "Home Movies"; the face
did not end in the ellipsis; "Фильмы 2" vs the type word), the rename test (left: "Home Movies" vs right: "Family Clips"), and compile errors
for the new accessors.

Simulator (1280x720, mock --other-videos 24; browse and UI only, no host FFmpeg): the strip with Home, Movies, TV Shows,
Other Videos, bookmark, Search; the Other Videos Library grid and its Sort & Filter (no "Show" section, Plays present);
Recommended page with the video.* shelves; Home row "Recently Added Videos" with a visible library and none with
--other-videos-hidden (pill present either way); the pill pressed from Search; a clip's detail page (no error line);
the count noun "24 videos" in Favorite libraries; de, ru, be and the pseudo-locale strip.

Pill title (mock --other-videos-title, 1280x720): one library "Home Movies" reads Home Movies; a 62-character title reads Family holidays...;
"Andere Videos" as a title is whole; two libraries read the type word; nine libraries read the type word and the Library header names them,
and after POST /_mock/config {"section_titles": ...} plus "Check for shared libraries" the header shows the new names without a restart;
in ru and be a 42-character title is elided (Family video..., Family vide...); in de a one-word title (Clips) draws the glass track and a long one the flat
capsule, as the model says. Movies and TV Shows are unchanged in every run. A rename of the pill itself in one process (as opposed to the header)
is covered by the data tests only.

Notes

  • Glass: the top track wears the glass material only up to a 672.3 px budget (tab_glass_on). On the shipped font's advances (a model of the
    television's text, not a television measurement) the two-type track is 621 px in English and 529-679 px across the shipped languages (Belarusian is
    already over the budget today). The translated "Other Videos" label makes the strip flat in every language; a library title keeps the glass only if its text
    is at most 91 px in German, 71 Portuguese, 65 Italian, 59 French, 38 Spanish (never in English, Hungarian, Russian, Belarusian). Pinned by
    the_two_type_track_is_measured_per_language_against_the_budget, the_translated_other_videos_pill_is_flat_in_every_language
    and a_library_title_keeps_the_glass_only_where_the_track_has_room; look at it on a TV. A rename can flip glass and flat
    in the five languages with room (de pt it fr es).
  • The pill title: server text, so it is not translated and not in any catalogue; elided to 189-240 px of text depending on the
    UI language so the chip keeps its 290 px (a 197 px title such as German "Andere Videos" is whole in every language but
    Belarusian); a rename shows after the next rediscovery, a deleted library stays until restart (both pre-existing limits
    of an append-only table); Arabic and Hebrew titles have no glyph in any shipped face (Arabic and Hebrew text in the UI (titles, track names, menus) #760, UI text: Arabic and Hebrew with RTL paragraphs #1007), while CJK and emoji
    titles draw through the bundled fallback faces (the elision is by character, so it can cut an emoji sequence or a combining
    mark: a plain prefix and the ellipsis remain). The Type menu and counts say "Other Videos"/"videos" even when the pill reads
    "Home Videos".
  • Commit subject: d5f5894e says "Other Videos never feed the hero"; what it does (and what the code comment now says) is
    that personal-video hubs never feed the recently-added families' hero allowance and pool. History is not rewritten.
  • Chip: the unfurled profile chip clears the track for names up to 294 px in Russian (the tightest; English 326, the
    name budget is 320); wider names overlap by at most 26 px while the chip, being focused, draws on top.
  • Fixture recipe: tests/fixtures/README.md and make_fixtures.py now say to keep the integration Movies library on the
    Plex Movie scanner. A library scanned with Plex Video Files is Other Videos to the app, which would move these
    real-PMS scenes off the Movies pill (those that arm plxnative-library as true/"0" and the Movies-pill routes in
    tests/manifest.json): poster-scroll-settle, poster-eviction-reversal, library-grid-paging-held-3g,
    library-grid-paging-held-remote-wan, library-shelf-paging-held-3g, library-shelf-paging-held-remote-wan,
    library-shelves-deep, library-burst, library-hold, library-scroll, library-collections, library-recommended,
    library-switch, library-idle. A maintainer whose library already uses the Video Files scanner re-scans it as Plex Movie
    or uses plxnative-library=2. The mock suites are unaffected (opt-in flag).
  • Behaviour note: a user who deliberately keeps films in an Other Videos library now finds them under the Other Videos pill.
  • Cross-PR: strip key STRIP_BASE + 7 (a compile-time assert refuses two destinations on one key whichever of Live TV: watch the server's channels, and a TV tab of channel covers #993 and
    this lands first); UI text: Arabic and Hebrew with RTL paragraphs #1007 (Arabic/Hebrew) will need these four keys in its two extra locales on rebase.
  • Not verified: the item type inside a visible library's global home.videos.recent hub (the measured library was
    hidden; if the items are clip-typed the row is empty and dropped, no crash); a friend's shared-token section row
    (agent/scanner present?; absent reads as Movies); the television (flat track, pill fit, chip overlap); playback of a
    clip; the Favorite-libraries switch in the simulator (a signed-out boot has no Favorite-libraries editor, so
    that step is covered by switching_the_other_videos_favourite_off_takes_only_its_pill only); with a visible library an
    in-progress clip reaches the hero through Continue Watching (the deck, not the excluded recently-added families).
  • Translations: English is the source. German "Andere Videos" is Plex's own label for the library type and is now only
    the fallback pill label, used when there are two libraries or the title is unusable (the German reviewer is asked to confirm it). Needs a native reviewer: es "Otros vídeos" (the existing es hub title says
    "Vídeos caseros": two words for one family, please harmonise), fr "Autres vidéos", it "Altri video", pt "Outros vídeos",
    hu "Egyéb videók", ru "Другие видео" and be "Іншае відэа" (the be strings are on the "Pending native review" list of
    docs/localization-belarusian-review.md). Keys: browse.kind.other_videos, browse.kind.videos,
    browse.library.videos, browse.library.no_videos.

Closes #599

Signed-off-by: Heiko Kopp 47413920+Bardioc1977@users.noreply.github.com

🤖 Generated with Claude Code

Bardioc1977 and others added 20 commits October 25, 2026 08:03
--other-videos N adds a third library filed the way Plex files "Other
Videos" (type movie, agent tv.plex.agents.none, scanner Plex Video Files,
hidden 0, or 1 with --other-videos-hidden) with N movie rows of subtype
clip, its three video.* clip hubs and the home.videos.recent hub on /hubs
(empty while the section is hidden, as measured on PMS 1.43).

The section key is 4: the GLinnik21#266 enhancement movies already use
librarySectionID 3.

/library/sections now composes agent, scanner and hidden from the
section's own dict, with the old literals as the defaults, so the
default answer keeps its bytes. Everything is off by default; the
generated-data hashes do not move.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
LibrarySection reads the section's agent and scanner (both "" when the
row has none) and answers is_other_videos(): type movie AND a "none"
agent (tv.plex.agents.none or the legacy com.plexapp.agents.none) AND a
scanner starting with "Plex Video Files". That pair is Plex's own
definition of an Other Videos library (measured on PMS 1.43.5).

Both halves are required: a false negative keeps today's behaviour (the
library stays under Movies), a false positive would move a curated
Movies library off its pill. A curated library keeps the Plex Movie
scanner, a hand-configured Movie agent with the Video Files scanner
stays Movies, and an older server's answer without the fields reads as
Movies. Nothing consumes the rule yet.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Four keys for the Other Videos library type, in en and the eight other
catalogues: browse.kind.other_videos (the pill and the Type menu row),
browse.kind.videos (the count placeholder and the crumb fallback),
browse.library.videos (plural count) and browse.library.no_videos.

English is the source. German "Andere Videos" is Plex's own label for
the library. The es, fr, it, pt, hu, ru and be strings are AI-drafted
proposals that need a native reviewer; the Belarusian ones are listed
under "Pending native review" in docs/localization-belarusian-review.md.
No code reads the keys yet.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
The strip's destination -> key map was written six times (Home, Library,
Recommended, Search and Watchlist each matched TAB_KEY_* by hand, and
the app's chrome, bridge and content each matched Pill/HomeTab/SecKind
again). Search and Watchlist ended their copy in a silent fallthrough,
so a new pill would have been dead on those two pages.

HomeTab now owns the map: strip_key, from_strip_key, section, of_kind
and ALL; Pill::tab goes through it; Home's STRIP_*_ELEM constants are
aliases of the TAB_KEYs. Behaviour-neutral: golden tests pin the keys
and every page has a test that presses every destination.

The TAB_KEY_* constants are declared by one strip_keys! macro that also
builds TAB_KEYS, with a compile-time pairwise-distinctness assert; a
test fails for a key declared beside it, so a key added later by
another change cannot escape the list.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Adds Plex's Other Videos as a library type next to Movies and Shows: the
SecKind variant (app code "video", slot 2, canon 2), its place after TV
Shows in TAB_KINDS, the LibraryType arms (the movie-shaped type menu,
count noun, empty read-out, Plays sort, plain `unwatched`), the Other
Videos pill (TAB_KEY_VIDEOS = STRIP_BASE + 7, HomeTab::Videos) and every
consumer of the kind: Library, Recommended and menu fingerprints and
canon codes, the crumb fallback, the dev triggers (plxnative-library=2)
and the recording vocabulary ("videos").

`household_type` is true for Video in lib_refs, so a friend's Other
Videos library stays Off by default (personal media never reaches a
household's Home unasked) and the household's own is On.

Nothing classifies a section as Video yet: project_sections still reads
the Plex type. The per-kind arrays are indexed by SecKind::slot() over
TAB_KINDS instead of two Movie/Show copies. Movie and Show keep their
canon codes, so SCREEN_SHAPES_PIN and the replay anchors do not move.
With a third type the track exceeds the glass budget (any fourth pill
does: 724 against 672), which a test now pins.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
A server with a Movies, a TV Shows and an Other Videos library answers
/library/sections with type movie for the third, told apart only by its
agent (tv.plex.agents.none) and scanner (Plex Video Files). The
projection still reads the Plex type alone, so the third section is a
Movies library:

  left:  [(1, "Movies", Movie), (2, "TV Shows", Show), (3, "Other Videos", Movie)]
  right: [(1, "Movies", Movie), (2, "TV Shows", Show), (3, "Other Videos", Video)]

The two tests beside it (a curated library with the none agent but the
Movie scanner, and an answer without agent or scanner stay Movies) pass
already and guard the fix against a false positive.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
project_sections now asks SecKind::of_section instead of reading the
Plex type alone: a movie library filed with no metadata agent and the
Plex Video Files scanner is Other Videos, everything else is Movies as
before (an answer without the fields too), and show stays Shows. This
turns the red test of the previous commit green and gives a household
with such a library the Other Videos pill, Library, Sources list and
Favorite-libraries switch of its own instead of an amalgam under
Movies (GLinnik21#599).

SecKind::from_wire keeps reading the app's own codes only (the
remembered library of a profile, a discovery recording); a Plex type
that spells "video" is not a library of the new kind.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
An Other Videos library's recently-added row is a hub of type clip
whose items are movie rows of subtype clip (measured on PMS 1.43.5).
Home admits a hub only when it is mixed or of a listable type, so such a
row never reaches a household whose server shows the library on Home;
and once it does, nothing keeps personal clips out of the hero.

Red on this commit:
- a_clip_hub_whose_items_are_movies_is_a_home_row: 0 hubs, want 1
- other_videos_never_feed_the_hero: 1 row of 3 (the clip rows are gone,
  so the hero exclusion it grades is not reached until the gate opens)
- a_refresh_spends_the_hero_allowance_...: 5 left, want 8 (the refresh
  spends the allowance on clip rows)
- an_unpinned_library_keeps_its_clip_row_off_home: no row to unpin
- video_recent_section_hub_is_titled_by_the_catalogue: the library's
  video.recent.<id> shelf is not in the recently-added family

Green already, as guards for the fix: a clip-typed extra is still not a
card, and a hub of an unlisted type (photo, album) is still skipped.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
…ent is worded by the catalogue

Home admitted a whole-server hub only when it was mixed or of a
listable type, so an Other Videos library's home.videos.recent (a hub
of type clip whose items are movie rows) never reached a household
whose server shows the library on Home. hub_listable now also takes
"clip"; the cards are still admitted on the ITEM type, which refuses a
clip-typed extra, and music and photo hubs stay out. A library the
server owner hid from the home screen (hidden 1 or 2) sends no rows
there, so it stays off Home and its pill is the way in.

The hero must not lead Home with a personal clip. Both places that
spend hero eligibility on a "recent" row (the pool and the refresh's
allowance in Projection::keeps) now read one predicate,
personal_video_hub, over the locale-independent ids home.videos.* and
video.*. With the gate opened and no predicate, the pool took both clip
rows first (["901", "902", "1"]).

hub_title adds the library's own video.recent.<id> shelf to the
recently-added family, so it wears the catalogue's wording like
movie.recentlyadded.* instead of the server's partly localised title.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
…anner

The sweep for what the change made false: the scope lines (README, the
site's FAQ answer and its JSON-LD copy, install-and-verify), the strip
(search.md, ux-scenario.md, parity-gaps.md, shared-servers.md, the ui
guide's key rule, liquid-glass.md on the flat track), and pms-api.md,
which now records the measured agent, scanner and hidden fields of a
section, the clip hub type of an Other Videos library and the `hidden`
values, and no longer says artist and photo sections are kept.

The integration fixture recipe built its Movies library with the
Personal Media (none) agent and named no scanner. Such a library is
Other Videos to the app when its scanner is Plex Video Files, which
would move the scenes that seat the Movies library off the Movies
pill; tests/fixtures/README.md and make_fixtures.py now say to keep it
on the Plex Movie scanner, and plxnative-library=2 seats Other Videos
(tests/README.md, mock_fps.library_section_index).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
ci/check-localization.py reads the two message strings of the
distinctness assert as product text. The assert keeps its conditions;
the build error names the line, which carries the sentence as a comment.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Seven contradictions the audit of the diff found: the favourite
default (a friend's Other Videos library is never On), the glass
budget's "room for one more library" (a third type is flat), the
remembered library's code (video is the app's own code, the wire type
is movie), the hub types and section fields the API catalogue lists,
the hero pool's "every recent variant", two section-table docs that
named two kinds, and the parity scope line. Comments and prose only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Brings in GLinnik21#1029 (the five ru keys the catalogue was missing).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Owner rule: exactly one favourite Other Videos library names the pill
after itself (server text, never translated, elided by character to the
room the strip leaves); two libraries, or a title that is empty, blank,
control-only or equal to another pill's label, keep the translated type
word. Movies and TV Shows keep their type words, and the Type menu and
counts keep "Other Videos".

The ten app-tier tests in chrome.rs (`other_videos_pill`) fail on the
branch because the face is always the translated word:
  one_other_videos_library_names_the_pill
    left: "Other Videos"  right: "Home Movies"
  two_other_videos_libraries_keep_the_type_label
    left: "Other Videos"  right: "Home Movies"  (one of two switched off)
  a_long_title_is_elided_to_the_room_the_strip_leaves
    the face "Other Videos" does not end in the ellipsis
  an_empty_blank_or_control_only_title_falls_back
    left: "Other Videos"  right: "Home Movies"  (a NUL becomes a space)
  format_characters_and_controls_are_cleaned
    left: "Other Videos"  right: "HomeMovies"
  a_title_equal_to_another_pill_falls_back
    left: "Other Videos"  right: "Movies 2"  (only an equal label collides)
  the_collision_test_uses_unicode_lowercase
    left: "Другие видео"  right: "Фильмы 2"
  the_title_is_not_translated, movies_and_tv_shows_pills_never_wear_a_
  library_title, a_cjk_or_emoji_title_does_not_panic_and_fits_or_ends_in_
  an_ellipsis likewise.

The mock PMS grows the opt-in options the simulator check needs, with
their tests (all green): `--other-videos-title NAME`,
`--other-videos-sections K` (further libraries hold no clips) and
`POST /_mock/config {"section_titles": {"4": "New name"}}` to stage a
server rename. A default library is byte-identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
Data half of the Other Videos pill naming its library. `tabs_gen` was
the strip's label generation but only moved with the favourite MASK, and
the table never took a new title for a section it already held, so a
rename (or a second library appearing) would have drawn the stale word.

- `SecKind::pill_wears_library_title` (Other Videos only) and ONE rule,
  `sole_favorite_title`: the trimmed title of the single favourite
  library of a kind that wears one, else the type word. BrowseState and
  DirectoryView both call it (`DirectoryView::tab_library_title`).
- `BrowseState::tab_titles` is stamped beside `tab_shape` by
  `refresh_tab_shape`, which moves `tabs_gen` when EITHER differs. Titles
  compare as borrowed strings and are cloned only on a change, so an idle
  table bump allocates nothing; a profile/server reset clears the stamp.
- `append_sections_with` now updates the title of a known (source, key)
  when it differs (a blank rename is ignored), with the usual
  `sections_gen` bump. Index, kind, pin and state are untouched. It
  applies at the next rediscovery (restart, profile or server switch,
  Sources re-check): nothing polls, and a library deleted on the server
  still stays until the table resets (pre-existing).

A household with two types computes "no title" forever, so its
`tabs_gen` sequence is the one it always had.

Observed red before the change: compile errors (`no field tab_titles`,
`no method pill_wears_library_title`, `cannot find function
sole_favorite_title`, `no method tab_library_title`); with the accessors
present and the title update disabled,
`a_rename_on_the_server_reaches_the_table_and_the_pill` fails with
left: "Home Movies" right: "Family Clips".

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
…nd elided to the room

The strip face for Other Videos is the translated type word, replaced
by the library's own title (`DirectoryView::tab_library_title`) when
`widgets::fit_title_face` can use it. It uses a title when:

- cleaning leaves something: control characters (NUL included, which
  `CString` would refuse and blank the pill) become spaces, format
  characters that draw nothing (soft hyphen, zero-width and bidi marks,
  BOM) are dropped, white space collapses, at most 128 characters are
  kept before measuring;
- no OTHER label pill says the same, compared in Unicode lowercase
  (`ФИЛЬМЫ` is `Фильмы`; two identical pills are one destination twice);
- the strip leaves at least 60 px of text. The budget is derived, not a
  constant: `title_budget` takes what 904 px of strip content (the width
  that keeps the unfurled chip its pinned 290 px, `TAB_TITLE_ROOM`)
  leaves after the other pills, gaps and padding, capped at 240 px. It
  is `Option<f32>` because `elide_by` returns its input UNCHANGED for a
  budget of zero or less; below the floor the translated word is kept.
  Shipped languages get 240 px (en de es fr it pt), 209 (hu), 202 (ru)
  and 189 (be); a 197 px title is whole in all but Belarusian.

The title is elided by character with the measure and size `tab_widths`
lays the strip out with. Home, Movies and TV Shows never pass through
the elision, so no recording sees a changed measurement query, and
`SCREEN_SHAPES_PIN` and the replay anchors do not move.

The glass figures were stale ("648 against 672, any fourth pill 724"):
the test pinned hand-picked label widths. On the shipped font's
advances (a model of the television's text, not a measurement) the
two-type track is 621 px in English and 529-679 across the nine
languages against 672.3, Belarusian already flat; the translated Other
Videos label is flat in all nine, and a library title keeps the glass
only up to 91 px of text in German, 71 pt, 65 it, 59 fr, 38 es (never
en, hu, ru, be). `the_two_type_track_is_measured_per_language_...`,
`the_translated_other_videos_pill_is_flat_in_every_language` and
`a_library_title_keeps_the_glass_only_where_the_track_has_room` pin
that; the chip-room test also runs with a 40-character title, through
the new `tab_chip_clearance`.

Red to green: the ten app-tier tests of the previous commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
The prose the Other Videos pill naming its library made false or
incomplete (doc-claim audit, two findings fixed):

- README, docs/search.md, docs/ux-scenario.md and the strip and
  tab-projection docs in widgets.rs and browse/mod.rs say that a pill
  is a type, with the one exception of a lone Other Videos library, whose
  pill wears its own title (never translated, elided to the room the
  strip leaves) and goes back to the type word with a second favourite.
- docs/liquid-glass.md replaces the stale "648 against 672, a third type
  pill takes the strip flat" with the per-language model figures: the
  two-type track is 621 px in English and 529-679 across the nine
  languages against 672.3; the translated label is flat everywhere, a
  library title keeps the glass only up to 91/71/65/59/38 px of text in
  de/pt/it/fr/es. A font model, not a television measurement.
- docs/parity-gaps.md: discovery never adds, removes or reorders a stop,
  but it can change the Other Videos pill's label.
- `sole_favorite_title`'s doc no longer promises an exclusion for
  disguised libraries that nothing implements.

Comments and prose only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
…spellings not measured

Wording corrections from the review of this branch (comments and prose
only; the earlier commit d5f5894 keeps its subject, which says "never
feed the hero" where "the recently-added families' hero" is meant):

- A personal-video hub (`home.videos.*`, `video.*`) is a Home row that
  never feeds the recently-added families' hero allowance and pool, not
  "never the hero": an in-progress clip of a visible library still
  reaches the hero through Continue Watching, the deck. Fixed in the
  `personal_video_hub` doc and the hero-pool comment (pms.rs), the test
  doc beside it and docs/pms-api.md.
- docs/pms-api.md section 1: the legacy spellings
  `com.plexapp.agents.none` and `Plex Video Files Scanner` no longer sit
  in the measured passage; they are marked as the older names from
  Plex's library documentation that no examined server answered. The
  example row now carries section key 3, the measured section on the
  real server.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
`the_title_is_not_translated` named three languages in a hand-written
list, which ci/check-language-lists.py refuses: a language added later
would ship untested. It now walks `i18n::SHIPPED`, asserts the title
stays the server's word and the two-library label is the translated type
word in each, and that the type word differs between languages.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>
The README says the Other Videos tab is named after the library when
exactly one Other Videos library is a favourite (the rule is the only
favourite, not the only library). The glass-budget test comment no
longer quotes a "0.7 px" Spanish figure that no test pins.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Kopp <47413920+Bardioc1977@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Other Videos" wrongly amalgamated into "Movies"

1 participant