# 080 — Library integration: info dialog and context menu

Status: approved 2026-09-30. Built in F4.

## 1. Actions

The same four actions everywhere; each takes the library item's data.

| Action (new router action) | Movie | TV show | Episode | Implementation |
|----------------------------|-------|---------|---------|----------------|
| `lib_sources` — Hledat zdroje | ✓ | — | ✓ | existing `show_search_dialog` params (`search_query`, `movie_title`, `movie_year`, `tmdb_id`, `is_episode`, `series_name`, `season_number`, `episode_number`, poster, plot) |
| `lib_game` — Milionář hra | ✓ | ✓ | ✓ | existing `play_text_game` (`title`, `tmdb_id`, `media_type`, `episode_title`, `season_number`, `episode_number`, `plot`, `poster`, `fanart`) |
| `lib_similar` — Podobné | ✓ | ✓ | — | existing `display_similar_movies_dialog` / `display_similar_series_dialog` (`tmdb_id`, `original_title`) |
| `lib_add_channel` — Přidat do MyTV / MyCinema | ✓ (cinema) | ✓ (channel) | ✓ (its show) | **new**: `xbmcgui.Dialog().select` of channels (+ "Nový kanál…"), then `MediaChannelManager(addon, 'movie'/'tv').toggle_media_in_channel`, notification, `widgets.invalidate` |

`wcs/skin/library_actions.py` resolves the input once:

- `tmdb_id` from `ListItem.UniqueID(tmdb)`; if empty, from JSON-RPC
  `VideoLibrary.Get*Details` `uniqueid`, then TMDb search by title/year
  (same resolution as `wcs/metadata/TMDbLogo.py`).
- For episodes the show's `tmdb_id` comes from `ListItem.TVShowDBID` →
  `VideoLibrary.GetTVShowDetails`.

## 2. Info dialog (`DialogVideoInfo.xml`)

Estuary's button row is a horizontal grouplist of `InfoDialogButton`
includes (ids 8, 11, 441, 101, 102, 13, 999, 14, 15, 443, 10, 6 in 21.3).
Add **one** `InfoDialogButton` "Milionář" (icon `icons/infodialogs/extras.png`,
id 4500 — unused in Estuary 21.3), placed last in the row, visible when `System.AddonIsEnabled(plugin.video.milionar) +
[String.IsEqual(ListItem.DBType,movie) | String.IsEqual(ListItem.DBType,tvshow)
| String.IsEqual(ListItem.DBType,episode)]`. Its `onclick` opens a
ButtonMenu dialog `Custom_1121_MilionarActions.xml` (same pattern as the
1108 settings menu, 050 §4) listing the actions of §1 valid for the DBType; each item runs
`RunPlugin(plugin://plugin.video.milionar/?action=lib_…&dbtype=$INFO[ListItem.DBType]&dbid=$INFO[ListItem.DBID]&tmdb=$INFO[ListItem.UniqueID(tmdb)])`.

Decided: one button with an action menu (not four buttons), so Estuary's
button row changes by exactly one button. Icon
`icons/infodialogs/extras.png` (050 §2).

The addon resolves everything else from `dbtype` + `dbid` through JSON-RPC,
so URLs stay short and need no escaping of titles.

## 3. Context menu (`addon.xml`, works in every skin)

```xml
<extension point="kodi.context.item">
  <menu id="kodi.core.main">
    <menu>
      <label>32NNN</label>                      <!-- "Milionář" -->
      <item library="context.py" args="lib_sources">
        <label>32NNN</label>
        <visible>[String.IsEqual(ListItem.DBType,movie) | String.IsEqual(ListItem.DBType,episode)] + !String.IsEmpty(ListItem.DBID)</visible>
      </item>
      <item library="context.py" args="lib_game">…</item>
      <item library="context.py" args="lib_similar">…</item>
      <item library="context.py" args="lib_add_channel">…</item>
    </menu>
  </menu>
</extension>
```

- Kodi 21.3 parses nested `<menu>`, `<item library args>`, numeric labels as
  addon strings, and requires `label`, `library` and `visible` on every item
  (source-verified, `ContextMenuAddon.cpp`). `sys.argv[1]` is the `args`
  value; `sys.listitem` is the selected item.
- `context.py` reads `DBType`/`DBID`/`UniqueID(tmdb)` from `sys.listitem`
  and calls `RunPlugin(…action=lib_…)`, so both entry points share one code
  path.
- Only library items (non-empty `ListItem.DBID`); plugin listings of the
  addon already have their own context menus (`wcs/ui/ContextMenu.py`).
- `addon.xml` changes need a Kodi restart to register the context items.

## 4. Result (F4, 2026-10-01)

- `wcs/skin/library_actions.py` + router actions `lib_sources`, `lib_game`,
  `lib_similar`, `lib_add_channel` (input `dbtype` + `dbid`; tmdb id from the
  library `uniqueid`, else a TMDb search). Sources reuse
  `play_movie_from_addon` / `play_episode_from_addon` (the addon's search
  dialog and playback), game reuses `play_text_game`, similar the existing
  similar dialogs, add-to-channel is a channel picker (+ "Nový kanál…") then
  `toggle_media_in_channel`.
- Info dialog: one `InfoDialogButton` id 4500 "Milionář" (last in the row)
  opens window 1121 (`Custom_1121_MilionarActions.xml`). The dialog's
  `ListItem` is not visible from the new window, so the button first stores
  `milionar.dbtype` / `milionar.dbid` as Home properties (three `onclick`s).
  Amended: the icon is `icons/infodialogs/launch.png` (rocket), because
  `extras.png` is already Estuary's "Extras" button for movies.
- Context menu: `addon.xml` `kodi.context.item` (submenu "Milionář", four
  items) + `context.py`; verified in Estuary and in skin.milionar, shown only
  for library movie / tvshow / episode.
- Verified live: button + menu in the movie info dialog (cast list focus and
  Info dialog unchanged: pixel-identical to Estuary, the new button sits
  off-screen in the default view), similar dialog (TMDb), add-to-cinema
  picker, game selection dialog, context menu in both skins.
- Fixed on the way: `DialogWcsTextGame.update_lifeline_buttons` raised
  `TypeError` (`setEnabled(None)`) before a game type was chosen.
- Not run: "Hledat zdroje" end to end (would start a real source search and
  possible autoplay).
