{# Library sub-menu labels/icons come from one place so the sidebar and the
hub can never disagree about what a media kind is called. #}
{% import "_library_nav.html" as libnav %}
{% block title %}MediaForge{% endblock %}
{# mf_components.css used to be linked per page. The queue hub (one window for
downloads/encoding/upscaling, further down in this file) sits on EVERY page
and uses .mf-progress / .mf-facet, so the sheet is loaded globally now.
Every selector in it is .mf-* scoped, so nothing else changes; the extra
per-page s that still exist are harmless duplicates. #}
{% block styles %}{% endblock %}
{# Theme pack (web/themes.py). Loaded LAST among stylesheets so a theme's
component overrides win the cascade against every core sheet above; the
built-in tokens in variables.css remain the fallback for everything a
theme does not define. The instance default is rendered server-side so
the very first paint is already themed; a user's personal override
(localStorage 'aw-themepack') is applied by the synchronous script below
before paint — same no-FOUC pattern as the dark/light bootstrap. #}
{# Shared HTML escaping (window.mfEscape / window.mfSafeUrl). In and
before every other script so inline blocks can use it too. #}
{# Visibility-aware polling (window.mfPoll) — see static/mf_poll.js. #}
{# Shared .mf-multiselect dropdown behaviour (window.mfMultiSelect) — see static/mf_multiselect.js. #}
{% if active_theme_pack %}
{% endif %}
{# Provider-pill scripts from enabled extensions (see
register_thirdparty(provider_pill_script=...) in
web/thirdparties/registry.py) — each one just calls
registerProviderPill() at load time, using the shim above, regardless
of whether app.js has loaded yet. Included on every page since pills
can render on any page with browse cards or a detail modal. #}
{% for script_url in provider_pill_scripts %}
{% endfor %}
{{ _('If MediaForge crashes unexpectedly, it can automatically send a technical error report (file/line/error type) plus basic system info (app version, OS, Python version) to the developer -- this helps find and fix bugs. Passwords, credentials and file contents are never included.') }}
{{ _('You can change this decision at any time under Settings -> Privacy & Telemetry. More extensive data points (e.g. download titles or watch behaviour) always stay separate, off by default, and individually toggled -- this question only covers crash reports and basic system info.') }}
{{ _('Move title') }}
{{ _('Move') }} {{ _('to a different location.') }}
{{ _('Moving') }} …
0%
Media Info
{{ _('Reading media information...') }}
🔒 {{ _('Solve Captcha') }}
{{ _('Loading browser screenshot...') }}
{% block scripts %}{% endblock %}
{{ _('Appearance') }}
{{ _('Accent Color') }}
10
10
100%
2x ▶▶
{{ _('Up next') }}
0:00 / --:--
{{ _('Starting transcoder...') }}
{{ _('Playback failed') }}
{{ _('Continue watching?') }}
{# hls.js, vendored (static/hls.min.js, upstream dist of v1.5.7). It used to
come from cdn.jsdelivr.net, which meant the player was dead on any install
without internet access -- a LAN-only container, or one behind Gluetun:
player.js falls back to video.canPlayType('application/vnd.apple.mpegurl'),
and Chrome and Firefox answer "" to that, so every play click ended in the
generic error branch. It also kept a third-party origin in the CSP. #}
{# Not epub-only: the same panel lists the bookmarks, and a PDF has
those too. Its chapter section simply stays empty. #}
{# The comic stage. Filled entirely from reader.js -- one or two
elements that are reused across page turns, never rebuilt. #}
{{ _('Contents and bookmarks') }}
{{ _('Bookmarks') }}
{{ _('Chapters') }}
{# Comic-only controls. They sit first because in comic mode every row
below them except Paper is hidden, and a panel that opens on its one
relevant control beats a panel that opens on a gap. #}
{{ _('Pages') }}
{{ _('Cover') }}
{{ _('Zoom') }}
{{ _('Fit') }}
{{ _('Typeface') }}
{{ _('Text size') }}
{{ _('Line spacing') }}
{{ _('Page width') }}
{{ _('Paper') }}
{{ _('Reading mode') }}
{# pdf.js (Apache-2.0, v3.11 legacy UMD build) and epub.js (BSD-2-Clause) with
its jszip dependency (MIT/GPL-3.0), all vendored for the same reason hls.js
is: an install without internet access must still be able to read a book,
and a CDN would put a third-party origin back into the CSP. The v3 build is
deliberate -- pdf.js v4 ships .mjs only, and pyproject.toml's package-data
globs are extension-specific, so a .mjs would silently not be packaged. #}