From 58078912c02b4f6d9bb49b97f71d80664c449664 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Fri, 10 Oct 2025 20:25:34 +0200 Subject: [PATCH 001/138] Moderation create user improvements and consistency, item source consistency --- src/Module/Moderation/Item/Source.php | 17 ++-- src/Module/Moderation/Users/Create.php | 17 ++-- view/lang/C/messages.po | 87 +++++++++---------- view/templates/moderation/item/source.tpl | 2 +- view/templates/moderation/users/create.tpl | 8 +- .../templates/moderation/users/create.tpl | 8 +- view/theme/frio/templates/register.tpl | 10 +-- 7 files changed, 74 insertions(+), 75 deletions(-) diff --git a/src/Module/Moderation/Item/Source.php b/src/Module/Moderation/Item/Source.php index 64858294eb..018429ae06 100644 --- a/src/Module/Moderation/Item/Source.php +++ b/src/Module/Moderation/Item/Source.php @@ -47,16 +47,16 @@ class Source extends BaseModeration $guid = basename($request['guid'] ?? $this->parameters['guid'] ?? ''); $item_uri = ''; - $item_id = ''; - $terms = []; - $source = ''; + $item_id = ''; + $terms = []; + $source = ''; if (!empty($guid)) { $item = Model\Post::selectFirst(['id', 'uri-id', 'guid', 'uri'], ['guid' => $guid]); if ($item) { - $item_id = $item['id']; + $item_id = $item['id']; $item_uri = $item['uri']; - $terms = Model\Tag::getByURIId($item['uri-id'], [Model\Tag::HASHTAG, Model\Tag::MENTION, Model\Tag::IMPLICIT_MENTION]); + $terms = Model\Tag::getByURIId($item['uri-id'], [Model\Tag::HASHTAG, Model\Tag::MENTION, Model\Tag::IMPLICIT_MENTION]); $activity = Model\Post\Activity::getByURIId($item['uri-id']); if (!empty($activity)) { @@ -68,7 +68,8 @@ class Source extends BaseModeration $tpl = Renderer::getMarkupTemplate('moderation/item/source.tpl'); return Renderer::replaceMacros($tpl, [ '$l10n' => [ - 'title' => $this->t('Item Source'), + 'title' => $this->t('Moderation'), + 'page' => $this->t('Item Source'), 'itemidlbl' => $this->t('Item Id'), 'itemurilbl' => $this->t('Item URI'), 'submit' => $this->t('Submit'), @@ -79,12 +80,12 @@ class Source extends BaseModeration 'urllbl' => $this->t('URL'), 'mentionlbl' => $this->t('Mention'), 'implicitlbl' => $this->t('Implicit Mention'), - 'error' => $this->tt('Error','Errors', 1), + 'error' => $this->tt('Error', 'Errors', 1), 'notfound' => $this->t('Item not found'), 'nosource' => $this->t('No source recorded'), 'noconfig' => !$this->config->get('debug', 'store_source') ? $this->t('Please make sure the debug.store_source config key is set in config/local.config.php for future items to have sources.') : '', ], - '$guid_field' => ['guid', $this->t('Item Guid'), $guid, ''], + '$guid_field' => ['guid', '', $guid, '', '', 'autofocus', '', $this->t('Item Guid')], '$guid' => $guid, '$item_uri' => $item_uri, '$item_id' => $item_id, diff --git a/src/Module/Moderation/Users/Create.php b/src/Module/Moderation/Users/Create.php index 6e16e37f4e..36a3a7a4a5 100644 --- a/src/Module/Moderation/Users/Create.php +++ b/src/Module/Moderation/Users/Create.php @@ -20,9 +20,9 @@ class Create extends BaseUsers self::checkFormSecurityTokenRedirectOnError('moderation/users/create', 'admin_users_create'); - $nu_name = $request['new_user_name'] ?? ''; + $nu_name = $request['new_user_name'] ?? ''; $nu_nickname = $request['new_user_nickname'] ?? ''; - $nu_email = $request['new_user_email'] ?? ''; + $nu_email = $request['new_user_email'] ?? ''; $nu_language = DI::config()->get('system', 'language'); if ($nu_name !== '' && $nu_email !== '' && $nu_nickname !== '') { @@ -44,18 +44,19 @@ class Create extends BaseUsers $t = Renderer::getMarkupTemplate('moderation/users/create.tpl'); return self::getTabsHTML('all') . Renderer::replaceMacros($t, [ // strings // - '$title' => $this->t('Administration'), - '$page' => $this->t('New User'), - '$submit' => $this->t('Add User'), + '$title' => $this->t('Moderation'), + '$page' => $this->t('Create user'), + '$description' => $this->t('Type in the details for the new user to be created.'), + '$submit' => $this->t('Create user'), '$form_security_token' => self::getFormSecurityToken('admin_users_create'), // values // '$query_string' => $this->args->getQueryString(), - '$newusername' => ['new_user_name', $this->t('Name'), '', $this->t('Name of the new user.')], - '$newusernickname' => ['new_user_nickname', $this->t('Nickname'), '', $this->t('Nickname of the new user.')], - '$newuseremail' => ['new_user_email', $this->t('Email'), '', $this->t('Email address of the new user.'), '', '', 'email'], + '$newusername' => ['new_user_name', '', '', '', true, 'autofocus', '', $this->t('Display name')], + '$newusernickname' => ['new_user_nickname', '', '', '', true, '', '', $this->t('Nickname')], + '$newuseremail' => ['new_user_email', '', '', '', true, 'email', '', $this->t('Email')], ]); } } diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 066fdf58fa..755fbbcbca 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2025.07-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-06 18:57+0200\n" +"POT-Creation-Date: 2025-10-10 20:47+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -440,7 +440,7 @@ msgstr "" #: src/Module/FriendSuggest.php:132 src/Module/Install.php:219 #: src/Module/Install.php:259 src/Module/Install.php:296 #: src/Module/Invite.php:162 src/Module/Item/Compose.php:188 -#: src/Module/Moderation/Item/Source.php:74 +#: src/Module/Moderation/Item/Source.php:75 #: src/Module/Moderation/Report/Create.php:153 #: src/Module/Moderation/Report/Create.php:168 #: src/Module/Moderation/Report/Create.php:196 @@ -1073,7 +1073,7 @@ msgstr "" #: src/Content/ContactSelector.php:122 #: src/Module/Moderation/Users/Active.php:82 #: src/Module/Moderation/Users/Blocked.php:82 -#: src/Module/Moderation/Users/Create.php:58 +#: src/Module/Moderation/Users/Create.php:59 #: src/Module/Moderation/Users/Deleted.php:69 #: src/Module/Moderation/Users/Index.php:89 #: src/Module/Moderation/Users/Index.php:109 @@ -2223,9 +2223,11 @@ msgstr "" #: src/Module/Moderation/Blocklist/Server/Import.php:105 #: src/Module/Moderation/Blocklist/Server/Index.php:84 #: src/Module/Moderation/Item/Delete.php:47 +#: src/Module/Moderation/Item/Source.php:71 #: src/Module/Moderation/Reports.php:99 src/Module/Moderation/Summary.php:64 #: src/Module/Moderation/Users/Active.php:89 #: src/Module/Moderation/Users/Blocked.php:89 +#: src/Module/Moderation/Users/Create.php:47 #: src/Module/Moderation/Users/Deleted.php:66 #: src/Module/Moderation/Users/Index.php:96 msgid "Moderation" @@ -2259,33 +2261,33 @@ msgstr "" msgid "last" msgstr "" -#: src/Content/Text/BBCode.php:900 +#: src/Content/Text/BBCode.php:909 #, php-format msgid "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:928 src/Model/Item.php:3618 -#: src/Model/Item.php:3624 src/Model/Item.php:3625 +#: src/Content/Text/BBCode.php:937 src/Model/Item.php:3622 +#: src/Model/Item.php:3628 src/Model/Item.php:3629 msgid "Link to source" msgstr "" -#: src/Content/Text/BBCode.php:1718 src/Content/Text/HTML.php:901 +#: src/Content/Text/BBCode.php:1727 src/Content/Text/HTML.php:901 msgid "Click to open/close" msgstr "" -#: src/Content/Text/BBCode.php:1773 +#: src/Content/Text/BBCode.php:1782 msgid "$1 wrote:" msgstr "" -#: src/Content/Text/BBCode.php:1847 src/Content/Text/BBCode.php:1848 +#: src/Content/Text/BBCode.php:1856 src/Content/Text/BBCode.php:1857 msgid "Encrypted content" msgstr "" -#: src/Content/Text/BBCode.php:2164 +#: src/Content/Text/BBCode.php:2173 msgid "Invalid source protocol" msgstr "" -#: src/Content/Text/BBCode.php:2183 +#: src/Content/Text/BBCode.php:2192 msgid "Invalid link protocol" msgstr "" @@ -2487,7 +2489,7 @@ msgid "Post to group" msgstr "" #: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1266 -#: src/Model/Profile.php:441 src/Module/Moderation/Item/Source.php:80 +#: src/Model/Profile.php:441 src/Module/Moderation/Item/Source.php:81 msgid "Mention" msgstr "" @@ -3437,44 +3439,44 @@ msgstr "" msgid "Sensitive content" msgstr "" -#: src/Model/Item.php:3518 +#: src/Model/Item.php:3522 msgid "bytes" msgstr "" -#: src/Model/Item.php:3549 +#: src/Model/Item.php:3553 #, php-format msgid "%2$s (%3$d%%, %1$d vote)" msgid_plural "%2$s (%3$d%%, %1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3551 +#: src/Model/Item.php:3555 #, php-format msgid "%2$s (%1$d vote)" msgid_plural "%2$s (%1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3556 +#: src/Model/Item.php:3560 #, php-format msgid "%d voter. Poll end: %s" msgid_plural "%d voters. Poll end: %s" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3558 +#: src/Model/Item.php:3562 #, php-format msgid "%d voter." msgid_plural "%d voters." msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3560 +#: src/Model/Item.php:3564 #, php-format msgid "Poll end: %s" msgstr "" -#: src/Model/Item.php:3601 src/Model/Item.php:3602 +#: src/Model/Item.php:3605 src/Model/Item.php:3606 msgid "View on separate page" msgstr "" @@ -3896,7 +3898,6 @@ msgstr "" #: src/Module/Admin/Site.php:442 src/Module/Admin/Storage.php:124 #: src/Module/Admin/Summary.php:183 src/Module/Admin/Themes/Details.php:82 #: src/Module/Admin/Themes/Index.php:103 src/Module/Admin/Tos.php:63 -#: src/Module/Moderation/Users/Create.php:47 #: src/Module/Moderation/Users/Pending.php:82 msgid "Administration" msgstr "" @@ -5704,7 +5705,7 @@ msgstr "" msgid "Delete Item" msgstr "" -#: src/Module/BaseModeration.php:110 src/Module/Moderation/Item/Source.php:71 +#: src/Module/BaseModeration.php:110 src/Module/Moderation/Item/Source.php:72 msgid "Item Source" msgstr "" @@ -6184,7 +6185,6 @@ msgstr "" #: src/Module/Moderation/Reports.php:105 #: src/Module/Moderation/Users/Active.php:82 #: src/Module/Moderation/Users/Blocked.php:82 -#: src/Module/Moderation/Users/Create.php:56 #: src/Module/Moderation/Users/Deleted.php:69 #: src/Module/Moderation/Users/Index.php:89 #: src/Module/Moderation/Users/Index.php:109 @@ -6745,7 +6745,7 @@ msgid "Result Item" msgstr "" #: src/Module/Debug/ActivityPubConversion.php:117 -#: src/Module/Moderation/Item/Source.php:82 +#: src/Module/Moderation/Item/Source.php:83 #: src/Module/Security/TwoFactor/Verify.php:84 msgid "Error" msgid_plural "Errors" @@ -7653,54 +7653,54 @@ msgstr "" msgid "The GUID of the item you want to delete." msgstr "" -#: src/Module/Moderation/Item/Source.php:72 +#: src/Module/Moderation/Item/Source.php:73 msgid "Item Id" msgstr "" -#: src/Module/Moderation/Item/Source.php:73 +#: src/Module/Moderation/Item/Source.php:74 msgid "Item URI" msgstr "" -#: src/Module/Moderation/Item/Source.php:75 +#: src/Module/Moderation/Item/Source.php:76 msgid "Terms" msgstr "" -#: src/Module/Moderation/Item/Source.php:76 +#: src/Module/Moderation/Item/Source.php:77 msgid "Tag" msgstr "" -#: src/Module/Moderation/Item/Source.php:77 +#: src/Module/Moderation/Item/Source.php:78 #: src/Module/Moderation/Users/Active.php:82 #: src/Module/Moderation/Users/Blocked.php:82 #: src/Module/Moderation/Users/Index.php:89 msgid "Type" msgstr "" -#: src/Module/Moderation/Item/Source.php:78 +#: src/Module/Moderation/Item/Source.php:79 msgid "Term" msgstr "" -#: src/Module/Moderation/Item/Source.php:79 +#: src/Module/Moderation/Item/Source.php:80 msgid "URL" msgstr "" -#: src/Module/Moderation/Item/Source.php:81 +#: src/Module/Moderation/Item/Source.php:82 msgid "Implicit Mention" msgstr "" -#: src/Module/Moderation/Item/Source.php:83 +#: src/Module/Moderation/Item/Source.php:84 msgid "Item not found" msgstr "" -#: src/Module/Moderation/Item/Source.php:84 +#: src/Module/Moderation/Item/Source.php:85 msgid "No source recorded" msgstr "" -#: src/Module/Moderation/Item/Source.php:85 +#: src/Module/Moderation/Item/Source.php:86 msgid "Please make sure the debug.store_source config key is set in config/local.config.php for future items to have sources." msgstr "" -#: src/Module/Moderation/Item/Source.php:87 +#: src/Module/Moderation/Item/Source.php:88 msgid "Item Guid" msgstr "" @@ -8041,27 +8041,20 @@ msgid "User \"%s\" unblocked" msgstr "" #: src/Module/Moderation/Users/Create.php:48 -msgid "New User" +#: src/Module/Moderation/Users/Create.php:50 +msgid "Create user" msgstr "" #: src/Module/Moderation/Users/Create.php:49 -msgid "Add User" -msgstr "" - -#: src/Module/Moderation/Users/Create.php:56 -msgid "Name of the new user." +msgid "Type in the details for the new user to be created." msgstr "" #: src/Module/Moderation/Users/Create.php:57 -msgid "Nickname" -msgstr "" - -#: src/Module/Moderation/Users/Create.php:57 -msgid "Nickname of the new user." +msgid "Display name" msgstr "" #: src/Module/Moderation/Users/Create.php:58 -msgid "Email address of the new user." +msgid "Nickname" msgstr "" #: src/Module/Moderation/Users/Deleted.php:67 diff --git a/view/templates/moderation/item/source.tpl b/view/templates/moderation/item/source.tpl index 14cb848a5e..1abef121d6 100644 --- a/view/templates/moderation/item/source.tpl +++ b/view/templates/moderation/item/source.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
-

{{$l10n.title}}

+

{{$l10n.title}} - {{$l10n.page}}

diff --git a/view/templates/moderation/users/create.tpl b/view/templates/moderation/users/create.tpl index bb83cb1d30..9b58918066 100644 --- a/view/templates/moderation/users/create.tpl +++ b/view/templates/moderation/users/create.tpl @@ -7,18 +7,20 @@

{{$title}} - {{$page}}

+

{{$description}}

+ - + - + - +
{{include file="field_input.tpl" field=$newusername}}{{include file="field_input.tpl" field=$newusername label=false}}
{{include file="field_input.tpl" field=$newusernickname}}{{include file="field_input.tpl" field=$newusernickname label=false}}
{{include file="field_input.tpl" field=$newuseremail}}{{include file="field_input.tpl" field=$newuseremail label=false}}
diff --git a/view/theme/frio/templates/moderation/users/create.tpl b/view/theme/frio/templates/moderation/users/create.tpl index a094d153d0..110fb56426 100644 --- a/view/theme/frio/templates/moderation/users/create.tpl +++ b/view/theme/frio/templates/moderation/users/create.tpl @@ -7,12 +7,14 @@

{{$title}} - {{$page}}

+

{{$description}}

+ - {{include file="field_input.tpl" field=$newusername}} - {{include file="field_input.tpl" field=$newusernickname}} - {{include file="field_input.tpl" field=$newuseremail}} + {{include file="field_input.tpl" field=$newusername label=false}} + {{include file="field_input.tpl" field=$newusernickname label=false}} + {{include file="field_input.tpl" field=$newuseremail label=false}}

diff --git a/view/theme/frio/templates/register.tpl b/view/theme/frio/templates/register.tpl index 2884c1cdaf..8ddbfd1147 100644 --- a/view/theme/frio/templates/register.tpl +++ b/view/theme/frio/templates/register.tpl @@ -27,7 +27,7 @@ {{if $oidlabel}}
- + {{$fillwith}} {{$fillext}}
@@ -36,7 +36,7 @@ {{if $invitations}}
- + {{$invite_desc nofilter}}
@@ -44,7 +44,7 @@
- +
@@ -52,13 +52,13 @@ {{if !$additional}}
- +
- +
{{/if}} From 2807e2747bd7fda8ef6353bf8135b12dc2771e1f Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sat, 11 Oct 2025 11:28:13 +0200 Subject: [PATCH 002/138] Minor update to docs to say frio is the default theme --- doc/Settings.md | 5 ++--- doc/de/Settings.md | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/Settings.md b/doc/Settings.md index 7ca0e22286..08a512c2ab 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -54,11 +54,10 @@ See [this help page](/help/translations) for more information about the translat Choose a theme to be the default system theme. This can be over-ridden by user profiles. -Default theme is `vier` at the moment. +Default theme is `frio` at the moment. You may also want to set a special theme for mobile interfaces. -Which may or may not be necessary depending of the mobile friendliness of the desktop theme you have chosen. -The `vier` theme for instance is mobile friendly. +It may or may not be necessary depending of the mobile friendliness of the desktop theme you have chosen. ### Registration diff --git a/doc/de/Settings.md b/doc/de/Settings.md index cee965ccaf..55be1313b1 100644 --- a/doc/de/Settings.md +++ b/doc/de/Settings.md @@ -47,10 +47,9 @@ Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Hier kann das Theme bestimmt werden, welches standardmäßig zum Anzeigen der Seite verwendet werden soll. Nutzer können in ihren Einstellungen andere Themes wählen. -Derzeit ist das "vier" Theme das vorausgewählte Theme. +Derzeit ist das "frio" Theme das vorausgewählte Theme. Für mobile Geräte kannst du ein spezielles Theme wählen, wenn das Standardtheme ungeeignet für mobile Geräte sein sollte. -Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzliches mobiles Theme. ### Registrierung From 62e2edb90b6904d3a123ff8caf7fbe27ce290513 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 15:03:58 +0200 Subject: [PATCH 003/138] Docs: Rename docs to lowercase, dash separated (credit nupplaphil) --- doc/{Accesskeys.md => access-keys.md} | 0 doc/{Account-Basics.md => account-basics.md} | 0 doc/{AddonStorageBackend.md => addon-storage-backend.md} | 0 doc/{Addons.md => addons.md} | 0 doc/{API-Entities.md => api-entities.md} | 0 doc/{API-Friendica.md => api-friendica.md} | 0 doc/{API-GNU-Social.md => api-gnu-social.md} | 0 doc/{API-Mastodon.md => api-mastodon.md} | 0 doc/{API-Twitter.md => api-twitter.md} | 0 doc/{BBCode.md => bbcode.md} | 0 doc/{Bugs-and-Issues.md => bugs-and-issues.md} | 0 doc/{Channels.md => channels.md} | 0 doc/{Chats.md => chats.md} | 0 doc/{Circles-and-Privacy.md => circles-and-privacy.md} | 0 doc/{Composer.md => composer.md} | 0 doc/{Config.md => config.md} | 0 doc/{Connectors.md => connectors.md} | 0 doc/de/{Account-Basics.md => account-basics.md} | 0 doc/de/{Addons.md => addons.md} | 0 doc/de/{BBCode.md => bbcode.md} | 0 doc/de/{Bugs-and-Issues.md => bugs-and-issues.md} | 0 doc/de/{Channels.md => channels.md} | 0 doc/de/{Chats.md => chats.md} | 0 doc/de/{Circles-and-Privacy.md => circles-and-privacy.md} | 0 doc/de/{Connectors.md => connectors.md} | 0 doc/de/{Developers.md => developers.md} | 0 doc/de/{Export-Import-Contacts.md => export-import-contacts.md} | 0 doc/de/{FAQ-admin.md => faq-admin.md} | 0 doc/de/{FAQ.md => faq.md} | 0 doc/de/{Groups.md => groups.md} | 0 doc/de/{Home.md => home.md} | 0 doc/de/{Improve-Performance.md => improve-performance.md} | 0 doc/de/{Install.md => install.md} | 0 doc/de/{Installing-Connectors.md => installing-connectors.md} | 0 doc/de/{Making-Friends.md => making-friends.md} | 0 doc/de/{Message-Flow.md => message-flow.md} | 0 doc/de/{Move-Account.md => move-account.md} | 0 doc/de/{Quick-Start-andfinally.md => quick-start-andfinally.md} | 0 ...uick-Start-groupsandpages.md => quick-start-groupsandpages.md} | 0 doc/de/{Quick-Start-guide.md => quick-start-guide.md} | 0 ...-Start-makingnewfriends.md => quick-start-makingnewfriends.md} | 0 doc/de/{Quick-Start-network.md => quick-start-network.md} | 0 doc/de/{README.md => readme.md} | 0 doc/de/{Remove-Account.md => remove-account.md} | 0 doc/de/{Settings.md => settings.md} | 0 doc/de/{SSL.md => ssl.md} | 0 doc/de/{Tags-and-Mentions.md => tags-and-mentions.md} | 0 doc/de/{Text_comment.md => text-comment.md} | 0 doc/de/{Text_editor.md => text-editor.md} | 0 ...-Domain-Driven-Design.md => developer-domain-driven-design.md} | 0 ...-Classes-to-src.md => developer-how-to-move-classes-to-src.md} | 0 doc/{Developers-Intro.md => developers-intro.md} | 0 doc/{Export-Import-Contacts.md => export-import-contacts.md} | 0 doc/{FAQ-admin.md => faq-admin.md} | 0 doc/{FAQ.md => faq.md} | 0 doc/{GitHub.md => github.md} | 0 doc/{Groups.md => groups.md} | 0 doc/{Home.md => home.md} | 0 doc/{Improve-Performance.md => improve-performance.md} | 0 doc/{Install.md => install.md} | 0 doc/{Installing-Connectors.md => installing-connectors.md} | 0 doc/{KeyboardShortcuts.md => keyboard-shortcuts.md} | 0 doc/{Making-Friends.md => making-friends.md} | 0 doc/{Message-Flow.md => message-flow.md} | 0 doc/{Migrate.md => migrate.md} | 0 doc/{Move-Account.md => move-account.md} | 0 doc/{Protocol.md => protocol.md} | 0 doc/{Quick-Start-andfinally.md => quick-start-andfinally.md} | 0 ...uick-Start-groupsandpages.md => quick-start-groupsandpages.md} | 0 doc/{Quick-Start-guide.md => quick-start-guide.md} | 0 ...-Start-makingnewfriends.md => quick-start-makingnewfriends.md} | 0 doc/{Quick-Start-network.md => quick-start-network.md} | 0 doc/{README.md => readme.md} | 0 doc/{Remove-Account.md => remove-account.md} | 0 doc/{Safety.md => safety.md} | 0 doc/{Settings.md => settings.md} | 0 doc/{SSL.md => ssl.md} | 0 doc/{StrategyHooks.md => strategy-hooks.md} | 0 doc/{Tags-and-Mentions.md => tags-and-mentions.md} | 0 doc/{Tests.md => tests.md} | 0 doc/{Text_comment.md => text-comment.md} | 0 doc/{Text_editor.md => text-editor.md} | 0 ...{Two-Factor-Authentication.md => two-factor-authentication.md} | 0 doc/{Update.md => update.md} | 0 doc/{Vagrant.md => vagrant.md} | 0 85 files changed, 0 insertions(+), 0 deletions(-) rename doc/{Accesskeys.md => access-keys.md} (100%) rename doc/{Account-Basics.md => account-basics.md} (100%) rename doc/{AddonStorageBackend.md => addon-storage-backend.md} (100%) rename doc/{Addons.md => addons.md} (100%) rename doc/{API-Entities.md => api-entities.md} (100%) rename doc/{API-Friendica.md => api-friendica.md} (100%) rename doc/{API-GNU-Social.md => api-gnu-social.md} (100%) rename doc/{API-Mastodon.md => api-mastodon.md} (100%) rename doc/{API-Twitter.md => api-twitter.md} (100%) rename doc/{BBCode.md => bbcode.md} (100%) rename doc/{Bugs-and-Issues.md => bugs-and-issues.md} (100%) rename doc/{Channels.md => channels.md} (100%) rename doc/{Chats.md => chats.md} (100%) rename doc/{Circles-and-Privacy.md => circles-and-privacy.md} (100%) rename doc/{Composer.md => composer.md} (100%) rename doc/{Config.md => config.md} (100%) rename doc/{Connectors.md => connectors.md} (100%) rename doc/de/{Account-Basics.md => account-basics.md} (100%) rename doc/de/{Addons.md => addons.md} (100%) rename doc/de/{BBCode.md => bbcode.md} (100%) rename doc/de/{Bugs-and-Issues.md => bugs-and-issues.md} (100%) rename doc/de/{Channels.md => channels.md} (100%) rename doc/de/{Chats.md => chats.md} (100%) rename doc/de/{Circles-and-Privacy.md => circles-and-privacy.md} (100%) rename doc/de/{Connectors.md => connectors.md} (100%) rename doc/de/{Developers.md => developers.md} (100%) rename doc/de/{Export-Import-Contacts.md => export-import-contacts.md} (100%) rename doc/de/{FAQ-admin.md => faq-admin.md} (100%) rename doc/de/{FAQ.md => faq.md} (100%) rename doc/de/{Groups.md => groups.md} (100%) rename doc/de/{Home.md => home.md} (100%) rename doc/de/{Improve-Performance.md => improve-performance.md} (100%) rename doc/de/{Install.md => install.md} (100%) rename doc/de/{Installing-Connectors.md => installing-connectors.md} (100%) rename doc/de/{Making-Friends.md => making-friends.md} (100%) rename doc/de/{Message-Flow.md => message-flow.md} (100%) rename doc/de/{Move-Account.md => move-account.md} (100%) rename doc/de/{Quick-Start-andfinally.md => quick-start-andfinally.md} (100%) rename doc/de/{Quick-Start-groupsandpages.md => quick-start-groupsandpages.md} (100%) rename doc/de/{Quick-Start-guide.md => quick-start-guide.md} (100%) rename doc/de/{Quick-Start-makingnewfriends.md => quick-start-makingnewfriends.md} (100%) rename doc/de/{Quick-Start-network.md => quick-start-network.md} (100%) rename doc/de/{README.md => readme.md} (100%) rename doc/de/{Remove-Account.md => remove-account.md} (100%) rename doc/de/{Settings.md => settings.md} (100%) rename doc/de/{SSL.md => ssl.md} (100%) rename doc/de/{Tags-and-Mentions.md => tags-and-mentions.md} (100%) rename doc/de/{Text_comment.md => text-comment.md} (100%) rename doc/de/{Text_editor.md => text-editor.md} (100%) rename doc/{Developer-Domain-Driven-Design.md => developer-domain-driven-design.md} (100%) rename doc/{Developer-How-To-Move-Classes-to-src.md => developer-how-to-move-classes-to-src.md} (100%) rename doc/{Developers-Intro.md => developers-intro.md} (100%) rename doc/{Export-Import-Contacts.md => export-import-contacts.md} (100%) rename doc/{FAQ-admin.md => faq-admin.md} (100%) rename doc/{FAQ.md => faq.md} (100%) rename doc/{GitHub.md => github.md} (100%) rename doc/{Groups.md => groups.md} (100%) rename doc/{Home.md => home.md} (100%) rename doc/{Improve-Performance.md => improve-performance.md} (100%) rename doc/{Install.md => install.md} (100%) rename doc/{Installing-Connectors.md => installing-connectors.md} (100%) rename doc/{KeyboardShortcuts.md => keyboard-shortcuts.md} (100%) rename doc/{Making-Friends.md => making-friends.md} (100%) rename doc/{Message-Flow.md => message-flow.md} (100%) rename doc/{Migrate.md => migrate.md} (100%) rename doc/{Move-Account.md => move-account.md} (100%) rename doc/{Protocol.md => protocol.md} (100%) rename doc/{Quick-Start-andfinally.md => quick-start-andfinally.md} (100%) rename doc/{Quick-Start-groupsandpages.md => quick-start-groupsandpages.md} (100%) rename doc/{Quick-Start-guide.md => quick-start-guide.md} (100%) rename doc/{Quick-Start-makingnewfriends.md => quick-start-makingnewfriends.md} (100%) rename doc/{Quick-Start-network.md => quick-start-network.md} (100%) rename doc/{README.md => readme.md} (100%) rename doc/{Remove-Account.md => remove-account.md} (100%) rename doc/{Safety.md => safety.md} (100%) rename doc/{Settings.md => settings.md} (100%) rename doc/{SSL.md => ssl.md} (100%) rename doc/{StrategyHooks.md => strategy-hooks.md} (100%) rename doc/{Tags-and-Mentions.md => tags-and-mentions.md} (100%) rename doc/{Tests.md => tests.md} (100%) rename doc/{Text_comment.md => text-comment.md} (100%) rename doc/{Text_editor.md => text-editor.md} (100%) rename doc/{Two-Factor-Authentication.md => two-factor-authentication.md} (100%) rename doc/{Update.md => update.md} (100%) rename doc/{Vagrant.md => vagrant.md} (100%) diff --git a/doc/Accesskeys.md b/doc/access-keys.md similarity index 100% rename from doc/Accesskeys.md rename to doc/access-keys.md diff --git a/doc/Account-Basics.md b/doc/account-basics.md similarity index 100% rename from doc/Account-Basics.md rename to doc/account-basics.md diff --git a/doc/AddonStorageBackend.md b/doc/addon-storage-backend.md similarity index 100% rename from doc/AddonStorageBackend.md rename to doc/addon-storage-backend.md diff --git a/doc/Addons.md b/doc/addons.md similarity index 100% rename from doc/Addons.md rename to doc/addons.md diff --git a/doc/API-Entities.md b/doc/api-entities.md similarity index 100% rename from doc/API-Entities.md rename to doc/api-entities.md diff --git a/doc/API-Friendica.md b/doc/api-friendica.md similarity index 100% rename from doc/API-Friendica.md rename to doc/api-friendica.md diff --git a/doc/API-GNU-Social.md b/doc/api-gnu-social.md similarity index 100% rename from doc/API-GNU-Social.md rename to doc/api-gnu-social.md diff --git a/doc/API-Mastodon.md b/doc/api-mastodon.md similarity index 100% rename from doc/API-Mastodon.md rename to doc/api-mastodon.md diff --git a/doc/API-Twitter.md b/doc/api-twitter.md similarity index 100% rename from doc/API-Twitter.md rename to doc/api-twitter.md diff --git a/doc/BBCode.md b/doc/bbcode.md similarity index 100% rename from doc/BBCode.md rename to doc/bbcode.md diff --git a/doc/Bugs-and-Issues.md b/doc/bugs-and-issues.md similarity index 100% rename from doc/Bugs-and-Issues.md rename to doc/bugs-and-issues.md diff --git a/doc/Channels.md b/doc/channels.md similarity index 100% rename from doc/Channels.md rename to doc/channels.md diff --git a/doc/Chats.md b/doc/chats.md similarity index 100% rename from doc/Chats.md rename to doc/chats.md diff --git a/doc/Circles-and-Privacy.md b/doc/circles-and-privacy.md similarity index 100% rename from doc/Circles-and-Privacy.md rename to doc/circles-and-privacy.md diff --git a/doc/Composer.md b/doc/composer.md similarity index 100% rename from doc/Composer.md rename to doc/composer.md diff --git a/doc/Config.md b/doc/config.md similarity index 100% rename from doc/Config.md rename to doc/config.md diff --git a/doc/Connectors.md b/doc/connectors.md similarity index 100% rename from doc/Connectors.md rename to doc/connectors.md diff --git a/doc/de/Account-Basics.md b/doc/de/account-basics.md similarity index 100% rename from doc/de/Account-Basics.md rename to doc/de/account-basics.md diff --git a/doc/de/Addons.md b/doc/de/addons.md similarity index 100% rename from doc/de/Addons.md rename to doc/de/addons.md diff --git a/doc/de/BBCode.md b/doc/de/bbcode.md similarity index 100% rename from doc/de/BBCode.md rename to doc/de/bbcode.md diff --git a/doc/de/Bugs-and-Issues.md b/doc/de/bugs-and-issues.md similarity index 100% rename from doc/de/Bugs-and-Issues.md rename to doc/de/bugs-and-issues.md diff --git a/doc/de/Channels.md b/doc/de/channels.md similarity index 100% rename from doc/de/Channels.md rename to doc/de/channels.md diff --git a/doc/de/Chats.md b/doc/de/chats.md similarity index 100% rename from doc/de/Chats.md rename to doc/de/chats.md diff --git a/doc/de/Circles-and-Privacy.md b/doc/de/circles-and-privacy.md similarity index 100% rename from doc/de/Circles-and-Privacy.md rename to doc/de/circles-and-privacy.md diff --git a/doc/de/Connectors.md b/doc/de/connectors.md similarity index 100% rename from doc/de/Connectors.md rename to doc/de/connectors.md diff --git a/doc/de/Developers.md b/doc/de/developers.md similarity index 100% rename from doc/de/Developers.md rename to doc/de/developers.md diff --git a/doc/de/Export-Import-Contacts.md b/doc/de/export-import-contacts.md similarity index 100% rename from doc/de/Export-Import-Contacts.md rename to doc/de/export-import-contacts.md diff --git a/doc/de/FAQ-admin.md b/doc/de/faq-admin.md similarity index 100% rename from doc/de/FAQ-admin.md rename to doc/de/faq-admin.md diff --git a/doc/de/FAQ.md b/doc/de/faq.md similarity index 100% rename from doc/de/FAQ.md rename to doc/de/faq.md diff --git a/doc/de/Groups.md b/doc/de/groups.md similarity index 100% rename from doc/de/Groups.md rename to doc/de/groups.md diff --git a/doc/de/Home.md b/doc/de/home.md similarity index 100% rename from doc/de/Home.md rename to doc/de/home.md diff --git a/doc/de/Improve-Performance.md b/doc/de/improve-performance.md similarity index 100% rename from doc/de/Improve-Performance.md rename to doc/de/improve-performance.md diff --git a/doc/de/Install.md b/doc/de/install.md similarity index 100% rename from doc/de/Install.md rename to doc/de/install.md diff --git a/doc/de/Installing-Connectors.md b/doc/de/installing-connectors.md similarity index 100% rename from doc/de/Installing-Connectors.md rename to doc/de/installing-connectors.md diff --git a/doc/de/Making-Friends.md b/doc/de/making-friends.md similarity index 100% rename from doc/de/Making-Friends.md rename to doc/de/making-friends.md diff --git a/doc/de/Message-Flow.md b/doc/de/message-flow.md similarity index 100% rename from doc/de/Message-Flow.md rename to doc/de/message-flow.md diff --git a/doc/de/Move-Account.md b/doc/de/move-account.md similarity index 100% rename from doc/de/Move-Account.md rename to doc/de/move-account.md diff --git a/doc/de/Quick-Start-andfinally.md b/doc/de/quick-start-andfinally.md similarity index 100% rename from doc/de/Quick-Start-andfinally.md rename to doc/de/quick-start-andfinally.md diff --git a/doc/de/Quick-Start-groupsandpages.md b/doc/de/quick-start-groupsandpages.md similarity index 100% rename from doc/de/Quick-Start-groupsandpages.md rename to doc/de/quick-start-groupsandpages.md diff --git a/doc/de/Quick-Start-guide.md b/doc/de/quick-start-guide.md similarity index 100% rename from doc/de/Quick-Start-guide.md rename to doc/de/quick-start-guide.md diff --git a/doc/de/Quick-Start-makingnewfriends.md b/doc/de/quick-start-makingnewfriends.md similarity index 100% rename from doc/de/Quick-Start-makingnewfriends.md rename to doc/de/quick-start-makingnewfriends.md diff --git a/doc/de/Quick-Start-network.md b/doc/de/quick-start-network.md similarity index 100% rename from doc/de/Quick-Start-network.md rename to doc/de/quick-start-network.md diff --git a/doc/de/README.md b/doc/de/readme.md similarity index 100% rename from doc/de/README.md rename to doc/de/readme.md diff --git a/doc/de/Remove-Account.md b/doc/de/remove-account.md similarity index 100% rename from doc/de/Remove-Account.md rename to doc/de/remove-account.md diff --git a/doc/de/Settings.md b/doc/de/settings.md similarity index 100% rename from doc/de/Settings.md rename to doc/de/settings.md diff --git a/doc/de/SSL.md b/doc/de/ssl.md similarity index 100% rename from doc/de/SSL.md rename to doc/de/ssl.md diff --git a/doc/de/Tags-and-Mentions.md b/doc/de/tags-and-mentions.md similarity index 100% rename from doc/de/Tags-and-Mentions.md rename to doc/de/tags-and-mentions.md diff --git a/doc/de/Text_comment.md b/doc/de/text-comment.md similarity index 100% rename from doc/de/Text_comment.md rename to doc/de/text-comment.md diff --git a/doc/de/Text_editor.md b/doc/de/text-editor.md similarity index 100% rename from doc/de/Text_editor.md rename to doc/de/text-editor.md diff --git a/doc/Developer-Domain-Driven-Design.md b/doc/developer-domain-driven-design.md similarity index 100% rename from doc/Developer-Domain-Driven-Design.md rename to doc/developer-domain-driven-design.md diff --git a/doc/Developer-How-To-Move-Classes-to-src.md b/doc/developer-how-to-move-classes-to-src.md similarity index 100% rename from doc/Developer-How-To-Move-Classes-to-src.md rename to doc/developer-how-to-move-classes-to-src.md diff --git a/doc/Developers-Intro.md b/doc/developers-intro.md similarity index 100% rename from doc/Developers-Intro.md rename to doc/developers-intro.md diff --git a/doc/Export-Import-Contacts.md b/doc/export-import-contacts.md similarity index 100% rename from doc/Export-Import-Contacts.md rename to doc/export-import-contacts.md diff --git a/doc/FAQ-admin.md b/doc/faq-admin.md similarity index 100% rename from doc/FAQ-admin.md rename to doc/faq-admin.md diff --git a/doc/FAQ.md b/doc/faq.md similarity index 100% rename from doc/FAQ.md rename to doc/faq.md diff --git a/doc/GitHub.md b/doc/github.md similarity index 100% rename from doc/GitHub.md rename to doc/github.md diff --git a/doc/Groups.md b/doc/groups.md similarity index 100% rename from doc/Groups.md rename to doc/groups.md diff --git a/doc/Home.md b/doc/home.md similarity index 100% rename from doc/Home.md rename to doc/home.md diff --git a/doc/Improve-Performance.md b/doc/improve-performance.md similarity index 100% rename from doc/Improve-Performance.md rename to doc/improve-performance.md diff --git a/doc/Install.md b/doc/install.md similarity index 100% rename from doc/Install.md rename to doc/install.md diff --git a/doc/Installing-Connectors.md b/doc/installing-connectors.md similarity index 100% rename from doc/Installing-Connectors.md rename to doc/installing-connectors.md diff --git a/doc/KeyboardShortcuts.md b/doc/keyboard-shortcuts.md similarity index 100% rename from doc/KeyboardShortcuts.md rename to doc/keyboard-shortcuts.md diff --git a/doc/Making-Friends.md b/doc/making-friends.md similarity index 100% rename from doc/Making-Friends.md rename to doc/making-friends.md diff --git a/doc/Message-Flow.md b/doc/message-flow.md similarity index 100% rename from doc/Message-Flow.md rename to doc/message-flow.md diff --git a/doc/Migrate.md b/doc/migrate.md similarity index 100% rename from doc/Migrate.md rename to doc/migrate.md diff --git a/doc/Move-Account.md b/doc/move-account.md similarity index 100% rename from doc/Move-Account.md rename to doc/move-account.md diff --git a/doc/Protocol.md b/doc/protocol.md similarity index 100% rename from doc/Protocol.md rename to doc/protocol.md diff --git a/doc/Quick-Start-andfinally.md b/doc/quick-start-andfinally.md similarity index 100% rename from doc/Quick-Start-andfinally.md rename to doc/quick-start-andfinally.md diff --git a/doc/Quick-Start-groupsandpages.md b/doc/quick-start-groupsandpages.md similarity index 100% rename from doc/Quick-Start-groupsandpages.md rename to doc/quick-start-groupsandpages.md diff --git a/doc/Quick-Start-guide.md b/doc/quick-start-guide.md similarity index 100% rename from doc/Quick-Start-guide.md rename to doc/quick-start-guide.md diff --git a/doc/Quick-Start-makingnewfriends.md b/doc/quick-start-makingnewfriends.md similarity index 100% rename from doc/Quick-Start-makingnewfriends.md rename to doc/quick-start-makingnewfriends.md diff --git a/doc/Quick-Start-network.md b/doc/quick-start-network.md similarity index 100% rename from doc/Quick-Start-network.md rename to doc/quick-start-network.md diff --git a/doc/README.md b/doc/readme.md similarity index 100% rename from doc/README.md rename to doc/readme.md diff --git a/doc/Remove-Account.md b/doc/remove-account.md similarity index 100% rename from doc/Remove-Account.md rename to doc/remove-account.md diff --git a/doc/Safety.md b/doc/safety.md similarity index 100% rename from doc/Safety.md rename to doc/safety.md diff --git a/doc/Settings.md b/doc/settings.md similarity index 100% rename from doc/Settings.md rename to doc/settings.md diff --git a/doc/SSL.md b/doc/ssl.md similarity index 100% rename from doc/SSL.md rename to doc/ssl.md diff --git a/doc/StrategyHooks.md b/doc/strategy-hooks.md similarity index 100% rename from doc/StrategyHooks.md rename to doc/strategy-hooks.md diff --git a/doc/Tags-and-Mentions.md b/doc/tags-and-mentions.md similarity index 100% rename from doc/Tags-and-Mentions.md rename to doc/tags-and-mentions.md diff --git a/doc/Tests.md b/doc/tests.md similarity index 100% rename from doc/Tests.md rename to doc/tests.md diff --git a/doc/Text_comment.md b/doc/text-comment.md similarity index 100% rename from doc/Text_comment.md rename to doc/text-comment.md diff --git a/doc/Text_editor.md b/doc/text-editor.md similarity index 100% rename from doc/Text_editor.md rename to doc/text-editor.md diff --git a/doc/Two-Factor-Authentication.md b/doc/two-factor-authentication.md similarity index 100% rename from doc/Two-Factor-Authentication.md rename to doc/two-factor-authentication.md diff --git a/doc/Update.md b/doc/update.md similarity index 100% rename from doc/Update.md rename to doc/update.md diff --git a/doc/Vagrant.md b/doc/vagrant.md similarity index 100% rename from doc/Vagrant.md rename to doc/vagrant.md From 692a12d562ff93ab8be8ae0c8e05fcb19d3d9961 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 15:29:34 +0200 Subject: [PATCH 004/138] Docs: Update filenames inside docs after rename --- doc/account-basics.md | 10 +-- doc/api-entities.md | 50 +++++++------- doc/api-friendica.md | 36 +++++----- doc/api-gnu-social.md | 4 +- doc/api-mastodon.md | 2 +- doc/api-twitter.md | 26 +++---- doc/api.md | 8 +-- doc/autoloader.md | 8 +-- doc/bbcode.md | 2 +- doc/composer.md | 6 +- doc/de/account-basics.md | 6 +- doc/de/export-import-contacts.md | 2 +- doc/de/faq-admin.md | 10 +-- doc/de/faq.md | 26 +++---- doc/de/home.md | 72 +++++++++---------- doc/de/quick-start-guide.md | 26 +++---- doc/de/settings.md | 2 +- doc/de/text-editor.md | 28 ++++---- doc/developer-domain-driven-design.md | 12 ++-- doc/developer-how-to-move-classes-to-src.md | 6 +- doc/developers-intro.md | 6 +- doc/export-import-contacts.md | 2 +- doc/faq-admin.md | 10 +-- doc/faq.md | 28 ++++---- doc/github.md | 2 +- doc/home.md | 76 ++++++++++----------- doc/making-friends.md | 2 +- doc/protocol.md | 2 +- doc/quick-start-guide.md | 2 +- doc/settings.md | 2 +- doc/tags-and-mentions.md | 2 +- doc/text-editor.md | 6 +- 32 files changed, 241 insertions(+), 241 deletions(-) diff --git a/doc/account-basics.md b/doc/account-basics.md index 975fd8fb76..c5a0c088c6 100644 --- a/doc/account-basics.md +++ b/doc/account-basics.md @@ -97,13 +97,13 @@ This might be necessary, e.g. if your node suffers a severe hardware problem and See Also --- -* [Profiles](help/Profiles) +* [Profiles](help/profiles) -* [Global Directory](help/Making-Friends#The+Directories) +* [Global Directory](help/making-friends#The+Directories) -* [Circles and Privacy](help/Circles-and-Privacy) +* [Circles and Privacy](help/circles-and-privacy) -* [Move Account](help/Move-Account) +* [Move Account](help/move-account) -* [Remove Account](help/Remove-Account) +* [Remove Account](help/remove-account) diff --git a/doc/api-entities.md b/doc/api-entities.md index de3eac9b9a..4e4512e7dc 100644 --- a/doc/api-entities.md +++ b/doc/api-entities.md @@ -18,31 +18,31 @@ like -List of Contacts +List of Contacts No dislike -List of Contacts +List of Contacts No attendyes -List of Contacts +List of Contacts No attendno -List of Contacts +List of Contacts No attendmaybe -List of Contacts +List of Contacts No @@ -330,31 +330,31 @@ Ex: Wed May 23 06:01:13 +0000 2007 hashtags -List of Hashtags +List of Hashtags No symbols -List of Symbols +List of Symbols No urls -List of URLs +List of URLs No user_mentions -List of User mentions +List of User mentions No media -List of Medias +List of Medias No @@ -570,13 +570,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 user -Contact +Contact No friendica_author -Contact +Contact No @@ -584,7 +584,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_owner -Contact +Contact No @@ -614,7 +614,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_activities -Activities +Activities No @@ -632,13 +632,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 attachments -List of Attachments +List of Attachments Yes entities -Entities +Entities Yes @@ -721,7 +721,7 @@ Identical to [the Twitter Media Object](https://developer.twitter.com/en/docs/tw sizes -Sizes +Sizes No @@ -1036,13 +1036,13 @@ Mutually exclusive with link. friendica_activities -Activities +Activities friendica_comments -List of Items +List of Items @@ -1260,13 +1260,13 @@ Mutually exclusive with link. sender -Contact +Contact recipient -Contact +Contact @@ -1471,25 +1471,25 @@ Mutually exclusive with link. medium -Size +Size No large -Size +Size Yes thumb -Size +Size Yes small -Size +Size Yes diff --git a/doc/api-friendica.md b/doc/api-friendica.md index 785cbe41a0..59157c8aaf 100644 --- a/doc/api-friendica.md +++ b/doc/api-friendica.md @@ -7,17 +7,17 @@ Friendica provides the following specific endpoints. -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/api#authentication). ## Entities -These endpoints uses the [Friendica API entities](help/API-Entities). +These endpoints uses the [Friendica API entities](help/api-entities). ## Endpoints ### GET api/friendica/events -Returns a list of [Event](help/API-Entities#Event) entities for the current logged in user. +Returns a list of [Event](help/api-entities#event) entities for the current logged in user. #### Parameters @@ -52,7 +52,7 @@ Delete event from calendar (not the message) ### GET api/externalprofile/show -Returns a [Contact](help/API-Entities#Contact) entity for the provided profile URL. +Returns a [Contact](help/api-entities#contact) entity for the provided profile URL. #### Parameters @@ -60,7 +60,7 @@ Returns a [Contact](help/API-Entities#Contact) entity for the provided profile U ### GET api/statuses/public_timeline -Returns a list of public [Items](help/API-Entities#Item) posted on this node. +Returns a list of public [Items](help/api-entities#item) posted on this node. Equivalent of the local community page. #### Parameters @@ -79,7 +79,7 @@ Equivalent of the local community page. ### GET api/statuses/networkpublic_timeline -Returns a list of public [Items](help/API-Entities#Item) this node is aware of. +Returns a list of public [Items](help/api-entities#item) this node is aware of. Equivalent of the global community page. #### Parameters @@ -206,7 +206,7 @@ Deprecated Twitter received direct message list endpoint. ### GET api/direct_messages/all -Returns all [Private Messages](help/API-Entities#Private+message). +Returns all [Private Messages](help/api-entities#private+message). #### Parameters @@ -219,7 +219,7 @@ Returns all [Private Messages](help/API-Entities#Private+message). ### GET api/direct_messages/conversation -Returns all replies of a single private message conversation. Returns [Private Messages](help/API-Entities#Private+message) +Returns all replies of a single private message conversation. Returns [Private Messages](help/api-entities#private+message) #### Parameters @@ -233,7 +233,7 @@ Returns all replies of a single private message conversation. Returns [Private M ### GET api/direct_messages/sent -Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/API-Entities#Private+message). +Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/api-entities#private+message). #### Parameters @@ -300,7 +300,7 @@ On error: ### GET api/friendica/direct_messages_search (GET; AUTH) -Returns [Private Messages](help/API-Entities#Private+message) matching the provided search string. +Returns [Private Messages](help/api-entities#private+message) matching the provided search string. #### Parameters @@ -339,7 +339,7 @@ Array of: * `name`: name of the circle * `gid`: id of the circle -* `user`: array of [Contacts](help/API-Entities#Contact) +* `user`: array of [Contacts](help/api-entities#contact) ### POST api/friendica/circle_create @@ -357,7 +357,7 @@ JSON data as Array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/API-Entities#Contact) +* List of [Contacts](help/api-entities#contact) #### Return values @@ -386,7 +386,7 @@ JSON data as array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/API-Entities#Contact) +* List of [Contacts](help/api-entities#contact) #### Return values @@ -423,7 +423,7 @@ Array of: ### GET api/friendica/notifications -Return last 50 [Notifications](help/API-Entities#Notification) for the current user, ordered by date with unseen item on top. +Return last 50 [Notifications](help/api-entities#notification) for the current user, ordered by date with unseen item on top. #### Parameters @@ -439,7 +439,7 @@ Set notification as seen. #### Return values -If the note is linked to an item, returns an [Item](help/API-Entities#Item). +If the note is linked to an item, returns an [Item](help/api-entities#item). Otherwise, a success status is returned: @@ -449,7 +449,7 @@ Otherwise, a success status is returned: ### GET api/friendica/photo -Returns a [Photo](help/API-Entities#Photo). +Returns a [Photo](help/api-entities#photo). #### Parameters @@ -523,7 +523,7 @@ xml: ### GET api/friendica/photos/list -Returns the API user's [Photo List Items](help/API-Entities#Photo+List+Item). +Returns the API user's [Photo List Items](help/api-entities#photo+list+item). #### Return values @@ -772,7 +772,7 @@ On success: ### GET api/friendica/profile/show -Returns the [Profile](help/API-Entities#Profile) data of the authenticated user. +Returns the [Profile](help/api-entities#profile) data of the authenticated user. #### Return values diff --git a/doc/api-gnu-social.md b/doc/api-gnu-social.md index a33825fc80..b41a3c4e7b 100644 --- a/doc/api-gnu-social.md +++ b/doc/api-gnu-social.md @@ -7,11 +7,11 @@ Friendica provides the following endpoints defined in [the official GNU Social Twitter-like API reference](https://gnusocial.net/doc/twitterapi). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/api#authentication). ## Entities -These endpoints use the [Friendica API entities](help/API-Entities). +These endpoints use the [Friendica API entities](help/api-entities). ## Implemented endpoints diff --git a/doc/api-mastodon.md b/doc/api-mastodon.md index 2cf661611b..f41682869e 100644 --- a/doc/api-mastodon.md +++ b/doc/api-mastodon.md @@ -11,7 +11,7 @@ Authentication is the same as described in [Using the APIs](help/api#Authenticat ## Clients -Please find a list of supported apps at [FAQ](help/FAQ#clients). +Please find a list of supported apps at [FAQ](help/faq#clients). ## Entities diff --git a/doc/api-twitter.md b/doc/api-twitter.md index fab26ae5b5..3a3832b6b2 100644 --- a/doc/api-twitter.md +++ b/doc/api-twitter.md @@ -7,11 +7,11 @@ Friendica provides the following endpoints defined in the [official Twitter API reference](https://developer.twitter.com/en/docs/api-reference-index). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/api#authentication). ## Entities -These endpoints use the [Friendica API entities](help/API-Entities). +These endpoints use the [Friendica API entities](help/api-entities). ## Different behaviour @@ -27,7 +27,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). * `cursor` * `trim_user` -* `contributor_details` +* `contributor_details` * `place_id` * `display_coordinates` * `include_rts`: To-Do @@ -57,7 +57,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). - `skip_status` - [POST api/account/update_profile_image](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image) - Additional parameter: - - `profile_id` (optional): Numerical id of the profile for which the image should be used, default is changing the default profile. + - `profile_id` (optional): Numerical id of the profile for which the image should be used, default is changing the default profile. - [POST api/statuses/update](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update) @@ -163,7 +163,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). - Unsupported parameter: - `skip_status`: No status is returned even if it isn't set to true. - Caveats: - - `cursor` trumps `since_id` trumps `max_id` if any combination is provided. + - `cursor` trumps `since_id` trumps `max_id` if any combination is provided. - `user_id` must be the ID of a contact associated with a local user account. - `screen_name` must be associated with a local user account. - `screen_name` trumps `user_id` if both are provided (undocumented Twitter behavior). @@ -243,8 +243,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [POST statuses/filter](https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter) - - + + - [GET statuses/mentions_timeline](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline) @@ -258,10 +258,10 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [GET statuses/sample](https://developer.twitter.com/en/docs/tweets/sample-realtime/api-reference/get-statuses-sample) - + - [GET compliance/firehose](https://developer.twitter.com/en/docs/tweets/compliance/api-reference/compliance-firehose) - + - [DELETE custom_profiles/destroy.json](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/delete-profile) - [GET custom_profiles/:id](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/get-profile) @@ -275,8 +275,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [POST direct_messages/events/new (message_create)](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-event) - [POST direct_messages/indicate_typing](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-typing-indicator) - [POST direct_messages/mark_read](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-read-receipt) - - + + - [DELETE direct_messages/welcome_messages/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message) - [DELETE direct_messages/welcome_messages/rules/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message-rule) - [PUT direct_messages/welcome_messages/update](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/update-welcome-message) @@ -299,8 +299,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [GET trends/available](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available) - [GET trends/closest](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-closest) - [GET trends/place](https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place) - - + + - [GET geo/id/:place_id](https://developer.twitter.com/en/docs/geo/place-information/api-reference/get-geo-id-place_id) - [GET geo/reverse_geocode](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-reverse_geocode) - [GET geo/search](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-search) diff --git a/doc/api.md b/doc/api.md index a3ca4d244d..044109705b 100644 --- a/doc/api.md +++ b/doc/api.md @@ -6,10 +6,10 @@ Friendica offers multiple API endpoints to interface with third-party applications: -- [Twitter](help/API-Twitter) -- [Mastodon](help/API-Mastodon) -- [Friendica-specific](help/API-Friendica) -- [GNU Social](help/API-GNU-Social) +- [Twitter](help/api-twitter) +- [Mastodon](help/api-mastodon) +- [Friendica-specific](help/api-friendica) +- [GNU Social](help/api-gnu-social) ## Usage diff --git a/doc/autoloader.md b/doc/autoloader.md index 5bc0bfe9b3..0f15119f7b 100644 --- a/doc/autoloader.md +++ b/doc/autoloader.md @@ -2,13 +2,13 @@ Autoloader with Composer ========== * [Home](help) - * [Developer Intro](help/Developers-Intro) + * [Developer Intro](help/developers-intro) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application. -* [Using Composer](help/Composer) +* [Using Composer](help/composer) ## A quick introduction to class autoloading @@ -198,5 +198,5 @@ So you can think of namespaces as folders in a Unix file system, with global sco ## Related -* [Using Composer](help/Composer) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [Using Composer](help/composer) +* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) diff --git a/doc/bbcode.md b/doc/bbcode.md index a39fb20d49..674a1b9d2a 100644 --- a/doc/bbcode.md +++ b/doc/bbcode.md @@ -1,7 +1,7 @@ Friendica BBCode tags reference ======================== -* [Creating posts](help/Text_editor) +* [Creating posts](help/text-editor) ## Inline diff --git a/doc/composer.md b/doc/composer.md index 7310a443eb..d68acba1c3 100644 --- a/doc/composer.md +++ b/doc/composer.md @@ -2,7 +2,7 @@ Using Composer ============== * [Home](help) - * [Developer Intro](help/Developers-Intro) + * [Developer Intro](help/developers-intro) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. @@ -55,7 +55,7 @@ If you don't need to use any third-party library, then you don't need to use Com #### Adding a third-party library to Friendica -Does your shiny new [Addon](help/Addons) need to rely on a third-party library not required by Friendica yet? +Does your shiny new [Addon](help/addons) need to rely on a third-party library not required by Friendica yet? First of all, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. This file is the configuration of Friendica for Composer. It lists details about the Friendica project, but also a list of required dependencies and their target version. @@ -117,4 +117,4 @@ $> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] bin/composer.phar [mode] ## Related * [Class autoloading](help/autoloader) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) diff --git a/doc/de/account-basics.md b/doc/de/account-basics.md index ef7ca4e63f..ce66818359 100644 --- a/doc/de/account-basics.md +++ b/doc/de/account-basics.md @@ -75,7 +75,7 @@ Bitte prüfe den Posteingang (inkl. dem Spam-Ordner). Gib auf der "Login"-Seite die Informationen ein, die Du mit der oben genannten Email erhalten hast. Du kannst entweder Deinen Spitznamen oder die Email-Adresse als Login-Namen nutzen. -Wenn Du Deinen Account nutzt, um unterschiedliche '[Seiten](help/Pages)' zu verwalten, die die gleiche Email-Adresse verwenden, dann nutze bitte den Spitznamen des Accounts, der verwaltet werden soll. +Wenn Du Deinen Account nutzt, um unterschiedliche '[Seiten](help/pages)' zu verwalten, die die gleiche Email-Adresse verwenden, dann nutze bitte den Spitznamen des Accounts, der verwaltet werden soll. *Wenn* Dein Account OpenID nutzt, dann kannst Du Deine OpenID-Adresse als Login-Name nutzen und das Passwort-Feld frei lassen. Du wirst zu Deinem OpenID-Anbieter weitergeleitet, wo Du Deine Anmeldung abschließt. @@ -109,9 +109,9 @@ Ein ['Tipp für neue Mitglieder'](newmember)-Link zeigt sich in den ersten beide ## Schau Dir ebenfalls folgende Seiten an -* [Circles und Privatssphäre](help/Circles-and-Privacy) +* [Circles und Privatssphäre](help/circles-and-privacy) -* [Account löschen](help/Remove-Account) +* [Account löschen](help/remove-account) ### Der eigene Friendica-Knoten Wenn Du Deinen eigenen Friendica-Knoten auf einem Server aufsetzen willst, kannst Du das ebenfalls machen. diff --git a/doc/de/export-import-contacts.md b/doc/de/export-import-contacts.md index b58752c9be..c4d28c646d 100644 --- a/doc/de/export-import-contacts.md +++ b/doc/de/export-import-contacts.md @@ -2,7 +2,7 @@ * [Home](help) -Zusätzlich zum [Umziehen des Accounts](help/Move-Account) kannst du die Liste der von dir gefolgten Kontakte exportieren und importieren. +Zusätzlich zum [Umziehen des Accounts](help/move-account) kannst du die Liste der von dir gefolgten Kontakte exportieren und importieren. Die exportierte Liste wird als CSV Datei in einem zu anderen Plattformen, z.B. Mastodon, Misskey oder Pleroma, kompatiblen Format gespeichert. ## Export der gefolgten Kontakte diff --git a/doc/de/faq-admin.md b/doc/de/faq-admin.md index 3b171afe51..1e05405db8 100644 --- a/doc/de/faq-admin.md +++ b/doc/de/faq-admin.md @@ -3,11 +3,11 @@ Häufig gestellte Fragen (Admin) - FAQ * [Zur Startseite der Hilfe](help) -* **[Kann ich mehrere Domains mit den selben Dateien aufsetzen?](help/FAQ-admin#multiple)** -* **[Wo kann ich den Quellcode von Friendica, Addons und Themes finden?](help/FAQ-admin#sources)** -* **[Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden?](help/FAQ-admin#adminaccount1)** -* **[Kann es mehr als einen Admin auf einer Friendica Instanz geben?](help/FAQ-admin#adminaccount2)** -* **[Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun?](help/FAQ-admin#dbupdate)** +* **[Kann ich mehrere Domains mit den selben Dateien aufsetzen?](help/faq-admin#multiple)** +* **[Wo kann ich den Quellcode von Friendica, Addons und Themes finden?](help/faq-admin#sources)** +* **[Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden?](help/faq-admin#adminaccount1)** +* **[Kann es mehr als einen Admin auf einer Friendica Instanz geben?](help/faq-admin#adminaccount2)** +* **[Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun?](help/faq-admin#dbupdate)** diff --git a/doc/de/faq.md b/doc/de/faq.md index 57d5569c15..53c70c99d3 100644 --- a/doc/de/faq.md +++ b/doc/de/faq.md @@ -3,16 +3,16 @@ Häufig gestellte Fragen - FAQ * [Zur Startseite der Hilfe](help) -* **[Wo finde ich Hilfe?](help/FAQ#help)** -* **[Warum erhalte ich Warnungen über fehlende Zertifikate?](help/FAQ#ssl)** -* **[Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen?](help/FAQ#upload)** -* **[Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben?](help/FAQ#avatars)** -* **[Wie kann ich Friendica in einer bestimmten Sprache ansehen?](help/FAQ#language)** -* **[Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?](help/FAQ#contacts)** -* **[Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht?](help/FAQ#removed)** -* **[Kann ich einem Hashtag folgen?](help/FAQ#hashtag)** -* **[Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen?](help/FAQ#rss)** -* **[Gibt es Clients für Friendica?](help/FAQ#clients)** +* **[Wo finde ich Hilfe?](help/faq#help)** +* **[Warum erhalte ich Warnungen über fehlende Zertifikate?](help/faq#ssl)** +* **[Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen?](help/faq#upload)** +* **[Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben?](help/faq#avatars)** +* **[Wie kann ich Friendica in einer bestimmten Sprache ansehen?](help/faq#language)** +* **[Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?](help/faq#contacts)** +* **[Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht?](help/faq#removed)** +* **[Kann ich einem Hashtag folgen?](help/faq#hashtag)** +* **[Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen?](help/faq#rss)** +* **[Gibt es Clients für Friendica?](help/faq#clients)** @@ -50,7 +50,7 @@ Diese Warnungen können drei Gründe haben: *(SSL (Secure Socket Layer) ist eine Technologie, die Daten auf ihrem Weg zwischen zwei Computern verschlüsselt.)* Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch letsencrypt) oder kreiere Dein eigenes (nicht empfohlen). -[Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/SSL) +[Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/ssl) Sei Dir bewusst, dass Browser-Warnungen über Sicherheitslücken etwas sind, wodurch neue Nutzer schnell das Vertrauen in das gesamte Friendica-Projekt verlieren können. Aus diesem Grund wird Friendica Red nur SSL-Zertifikate eines anerkannten Anbieters (CA, certificate authority) akzeptieren und nicht zu Seiten verbinden, die kein SSL nutzen. @@ -68,7 +68,7 @@ Andere erlauben nur kostenpflichtige Zertifikate als eigenes Angebot bzw. von an ### Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen? -Bilder können direkt im [Beitragseditor](help/Text_editor) vom Computer hochgeladen werden. +Bilder können direkt im [Beitragseditor](help/text-editor) vom Computer hochgeladen werden. Eine Übersicht aller Bilder, die auf Deinem Server liegen, findest Du unter deineSeite.de/profile/profilname/photos. Dort kannst Du auch direkt Bilder hochladen und festlegen, ob Deine Kontakte eine Nachricht über das neue Bild bekommen. @@ -180,7 +180,7 @@ Beispiel: Friendica Support ### Gibt es Clients für Friendica? -Friendica unterstützt [Mastodon API](help/API-Mastodon) und [Twitter API | gnusocial](help/api). +Friendica unterstützt [Mastodon API](help/api-mastodon) und [Twitter API | gnusocial](help/api). Das bedeutet, du kannst einge der Mastodon und Twitter Clients für Friendica verwenden. Die verfügbaren Features sind Abhängig vom Client, so dass diese teils unterschiedlich sein können. diff --git a/doc/de/home.md b/doc/de/home.md index 6ea7937ea3..d03848b4a4 100644 --- a/doc/de/home.md +++ b/doc/de/home.md @@ -4,61 +4,61 @@ Hilfe **Dokumentation für Benutzer** * Allgemeine Funktionen - Erste Schritte - * [Account - Basics](help/Account-Basics) - * [Schnellstart für neue Benutzer](help/Quick-Start-guide) - * [Beiträge erstellen](help/Text_editor) - * [Referenz der BBCode Elemente](help/BBCode) - * [Beiträge kommentieren, einordnen und löschen](help/Text_comment) - * [Referenz der Accesskeys](help/Accesskeys) + * [Account - Basics](help/account-basics) + * [Schnellstart für neue Benutzer](help/quick-start-guide) + * [Beiträge erstellen](help/text-editor) + * [Referenz der BBCode Elemente](help/bbcode) + * [Beiträge kommentieren, einordnen und löschen](help/text-comment) + * [Referenz der Accesskeys](help/access-keys) * [Veranstaltungen](help/events) * Du und andere Nutzer - * [Konnektoren (Connectors)](help/Connectors) - * [Freunde finden](help/Making-Friends) - * [Circles und Privatsphäre](help/Circles-and-Privacy) - * [Tags und Erwähnungen](help/Tags-and-Mentions) - * [Community-Gruppen](help/Groups) - * [Kanäle (Channels)](help/Channels) - * [Chats](help/Chats) + * [Konnektoren (Connectors)](help/connectors) + * [Freunde finden](help/making-friends) + * [Circles und Privatsphäre](help/circles-and-privacy) + * [Tags und Erwähnungen](help/tags-and-mentions) + * [Community-Gruppen](help/groups) + * [Kanäle (Channels)](help/channels) + * [Chats](help/chats) * Weiterführende Informationen - * [Account umziehen](help/Move-Account) - * [Export / Import gefolgter Kontakte](help/Export-Import-Contacts) - * [Account löschen](help/Remove-Account) - * [Bugs und Probleme](help/Bugs-and-Issues) - * [Häufig gestellte Fragen (FAQ)](help/FAQ) + * [Account umziehen](help/move-account) + * [Export / Import gefolgter Kontakte](help/export-import-contacts) + * [Account löschen](help/remove-account) + * [Bugs und Probleme](help/bugs-and-issues) + * [Häufig gestellte Fragen (FAQ)](help/faq) **Dokumentation für Administratoren** -* [Installation](help/Install) -* [Update](help/Update) (EN) -* [Konfigurationen & Admin-Panel](help/Settings) -* [Addons](help/Addons) -* [Konnektoren (Connectors) installieren](help/Installing-Connectors) +* [Installation](help/install) +* [Update](help/update) (EN) +* [Konfigurationen & Admin-Panel](help/settings) +* [Addons](help/addons) +* [Konnektoren (Connectors) installieren](help/installing-connectors) * [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN) -* [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL) -* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/Config) (EN) -* [Performance verbessern](help/Improve-Performance) +* [Betreibe deine Seite mit einem SSL-Zertifikat](help/ssl) +* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/config) (EN) +* [Performance verbessern](help/improve-performance) * [Administration Werkzeuge](help/tools) (EN) -* [Admin FAQ](help/FAQ-admin) +* [Admin FAQ](help/faq-admin) **Dokumentation für Entwickler** -* [Entwickler](help/Developers) -* [Where to get started?](help/Developers-Intro) (EN) -* [Help on Github](help/Github) -* [Help on Vagrant](help/Vagrant) +* [Entwickler](help/developers) +* [Where to get started?](help/developers-intro) (EN) +* [Help on Github](help/github) +* [Help on Vagrant](help/vagrant) * [How to translate Friendica](help/translations) (EN) -* [Bugs and Issues](help/Bugs-and-Issues) -* [Addon Development](help/Addons) +* [Bugs and Issues](help/bugs-and-issues) +* [Addon Development](help/addons) * [Theme Development](help/themes) * [Smarty 3 Templates](help/smarty3-templates) -* [Protokoll Dokumentation](help/Protocol) (EN) +* [Protokoll Dokumentation](help/protocol) (EN) * [Datenbank-Schema](help/database) * [Class Autoloading](help/autoloader) (EN) -* [Using Composer](help/Composer) (EN) +* [Using Composer](help/composer) (EN) * [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/) * [API Dokumentation](help/api) (EN) * [Translation of Friendica](help/translations) (EN) -* [Run tests](help/Tests) (EN) +* [Run tests](help/tests) (EN) **Links** diff --git a/doc/de/quick-start-guide.md b/doc/de/quick-start-guide.md index 6260bf97fc..41dc0c3102 100644 --- a/doc/de/quick-start-guide.md +++ b/doc/de/quick-start-guide.md @@ -1,23 +1,23 @@ -Erste Schritte... +Erste Schritte... ========== * [Zur Startseite der Hilfe](help) -Als Erstes: Gehe sicher, dass Du eingeloggt bist. -Wenn Du noch nicht eingeloggt bist, kannst Du das in dem Fenster unten machen. +Als Erstes: Gehe sicher, dass Du eingeloggt bist. +Wenn Du noch nicht eingeloggt bist, kannst Du das in dem Fenster unten machen. -Sobald dies geschehen ist, schaust Du auf die Netzwerkseite Deines Profils. +Sobald dies geschehen ist, schaust Du auf die Netzwerkseite Deines Profils. Klicke auf den Reiter "Pinnwand". -Hier sieht es ein wenig wie auf (D)einer Facebook-Seite aus. -Du findest hier alle Deine Statusmeldungen und Nachrichten Deiner Freunde, die direkt auf Deine "Pinnwand" ("Wall") geschrieben haben. -Um Deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. -Wenn Du das machst, vergrößert sich die Box, und Du kannst nun Deinen Text eintragen, mit Hilfe einiger Formatierungsoptionen wie fett, kursiv, unterstrichen formatieren und ebenfalls Bilder und Links hinzufügen. -Unten findest Du in diesem Feld weitere Knöpfe, mit denen Du Bilder und Dateien von Deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. -Außerdem kannst Du hier eintragen, wo Du gerade bist. +Hier sieht es ein wenig wie auf (D)einer Facebook-Seite aus. +Du findest hier alle Deine Statusmeldungen und Nachrichten Deiner Freunde, die direkt auf Deine "Pinnwand" ("Wall") geschrieben haben. +Um Deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. +Wenn Du das machst, vergrößert sich die Box, und Du kannst nun Deinen Text eintragen, mit Hilfe einiger Formatierungsoptionen wie fett, kursiv, unterstrichen formatieren und ebenfalls Bilder und Links hinzufügen. +Unten findest Du in diesem Feld weitere Knöpfe, mit denen Du Bilder und Dateien von Deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. +Außerdem kannst Du hier eintragen, wo Du gerade bist. -Wenn Du Deinen Beitrag ("Post") geschrieben hast, kannst Du auf das "Schloss"-Symbol klicken und festlegen, wer Deinen Beitrag sehen kann. -Wenn Du dieses Symbol nicht anklickst, ist Dein Beitrag öffentlich, bzw. es werden deine Grundeinstellungen verwendet, wenn diese nicht öffentlich sind. +Wenn Du Deinen Beitrag ("Post") geschrieben hast, kannst Du auf das "Schloss"-Symbol klicken und festlegen, wer Deinen Beitrag sehen kann. +Wenn Du dieses Symbol nicht anklickst, ist Dein Beitrag öffentlich, bzw. es werden deine Grundeinstellungen verwendet, wenn diese nicht öffentlich sind. Ein öffentlicher Beitrag ist sichbar für
    @@ -30,7 +30,7 @@ Auch wenn Du Deinen Server so konfiguriert hast, dass der Zugriff von außerhalb -Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den "Netzwerk"-Tab an. +Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den "Netzwerk"-Tab an. diff --git a/doc/de/settings.md b/doc/de/settings.md index 55be1313b1..0251195c28 100644 --- a/doc/de/settings.md +++ b/doc/de/settings.md @@ -415,4 +415,4 @@ Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein w ## Weitere Ausnahmen Es gibt noch einige experimentelle Einstellungen, die nur in der ``config/local.config.php`` Datei konfiguriert werden können. -Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/Config) Artikel kannst du mehr darüber erfahren. +Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/config) Artikel kannst du mehr darüber erfahren. diff --git a/doc/de/text-editor.md b/doc/de/text-editor.md index 4c71ae559d..062dd1f7f8 100644 --- a/doc/de/text-editor.md +++ b/doc/de/text-editor.md @@ -3,9 +3,9 @@ Beiträge erstellen * [Zur Startseite der Hilfe](help) -Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, deinen Beitrag zu bearbeiten. +Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, deinen Beitrag zu bearbeiten. -Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. +Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. @@ -13,36 +13,36 @@ Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht ode Die einzelnen Symbole -editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. -Wenn du eine Internetadresse (URL) eingeben willst, dann kannst du das "Baum"-Symbol im oberen Teil des Editors nutzen. +editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. +Wenn du eine Internetadresse (URL) eingeben willst, dann kannst du das "Baum"-Symbol im oberen Teil des Editors nutzen. Wenn du ein Bild ausgewählt hast, dann erscheint eine Miniaturdarstellung des Bildes im Editor.*

    paper_clip Wenn du dieses Symbol anklickst, dann kannst du weitere Dateien von deinem Computer einfügen. Eine Vorschau des Dateiinhalts erfolgt nicht.*

    -chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. +chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. Im Editor erscheint automatisch eine kurze Information zum eingefügten Link.*

    -video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. -Das Video erscheint dann mit einem Player in deinem Beitrag. -Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser verschiedene Videoformate unterstützt (z.B. WebM oder MP4). -Außerdem kannst du hier die URLs von Videos auf Youtube, Vimeo und manchen anderen Videohostern eingeben. +video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. +Das Video erscheint dann mit einem Player in deinem Beitrag. +Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser verschiedene Videoformate unterstützt (z.B. WebM oder MP4). +Außerdem kannst du hier die URLs von Videos auf Youtube, Vimeo und manchen anderen Videohostern eingeben. Die Videos werden dann mit Vorschaubild angezeigt, nach einem Klick öffnet sich ein eingebetteter Player.*

    -mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. -Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser und Betriebssystem MP3, Ogg oder AAC unterstützt. +mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. +Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser und Betriebssystem MP3, Ogg oder AAC unterstützt. Außerdem kannst du hier auch URLs von manchen Audiohostern wie Soundcloud eingeben, um eine dort gespeicherte Audiodatei mit Player in deinem Beitrag anzuzeigen.*

    -globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. -Hier reicht schon eine Angabe wie "Berlin" oder "10775". +globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. +Hier reicht schon eine Angabe wie "Berlin" oder "10775". Dieser Eintrag führt anschließend zu einer Suchanfrage bei Google Maps.

    -* wie du Dateien hochladen kannst, erfährst du [hier](help/FAQ#upload) +* wie du Dateien hochladen kannst, erfährst du [hier](help/faq#upload) **Im Folgenden findest du Symbole weiterer Themen** diff --git a/doc/developer-domain-driven-design.md b/doc/developer-domain-driven-design.md index 3052074443..8f3e58193a 100644 --- a/doc/developer-domain-driven-design.md +++ b/doc/developer-domain-driven-design.md @@ -2,7 +2,7 @@ Domain-Driven-Design ============== * [Home](help) - * [Developer Intro](help/Developers-Intro) + * [Developer Intro](help/developers-intro) Friendica uses class structures inspired by Domain-Driven-Design programming patterns. This page is meant to explain what it means in practical terms for Friendica development. @@ -85,7 +85,7 @@ class Model { $this->dba = $dba; } - + function save() { return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]); @@ -136,7 +136,7 @@ class Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } } @@ -170,7 +170,7 @@ class Model { $this->dba = $dba; } - + function save() { return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]); @@ -191,7 +191,7 @@ class Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } } @@ -223,7 +223,7 @@ class Repository extends Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } public function save(Model $model) diff --git a/doc/developer-how-to-move-classes-to-src.md b/doc/developer-how-to-move-classes-to-src.md index c33df3d729..948ad5584d 100644 --- a/doc/developer-how-to-move-classes-to-src.md +++ b/doc/developer-how-to-move-classes-to-src.md @@ -2,9 +2,9 @@ How To Move Classes to `src` ============== * [Home](help) - * [Developer Intro](help/Developers-Intro) + * [Developer Intro](help/developers-intro) -Friendica uses [Composer](help/Composer) to manage autoloading. +Friendica uses [Composer](help/composer) to manage autoloading. This means that all the PHP class files moved to the `src` folder will be [automatically included](help/autoloader) when the class it defines is first used in the flow. This is an improvement over the current `require` usage since files will be included on an actual usage basis instead of the presence of a `require` call. @@ -105,4 +105,4 @@ Most of the time it's used for debugging purposes but there can be instances whe ## Related * [Class autoloading](help/autoloader) -* [Using Composer](help/Composer) \ No newline at end of file +* [Using Composer](help/composer) diff --git a/doc/developers-intro.md b/doc/developers-intro.md index 5dbf1def4a..3171f6c5c2 100644 --- a/doc/developers-intro.md +++ b/doc/developers-intro.md @@ -41,7 +41,7 @@ If you have seen Friendica you probably have ideas to improve it, haven't you? ## Programming -Friendica uses an implementation of [Domain-Driven-Design](help/Developer-Domain-Driven-Design), please make sure to check out the provided links for hints at the expected code architecture. +Friendica uses an implementation of [Domain-Driven-Design](help/developer-domain-driven-design), please make sure to check out the provided links for hints at the expected code architecture. ### Composer @@ -67,8 +67,8 @@ If you want to have git automatically update the dependencies with composer, you just place it into `.git/hooks/post-merge` and make it executable. * [Class autoloading](help/autoloader) -* [Using Composer](help/Composer) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [Using Composer](help/composer) +* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) ### Coding standards diff --git a/doc/export-import-contacts.md b/doc/export-import-contacts.md index 824c9e2ebb..bb8c5d00f5 100644 --- a/doc/export-import-contacts.md +++ b/doc/export-import-contacts.md @@ -2,7 +2,7 @@ * [Home](help) -In addition to [move your account](help/Move-Account) you can export and import the list of accounts you follow. +In addition to [move your account](help/move-account) you can export and import the list of accounts you follow. The exported list is stored as CSV file that is compatible to the format used by other platforms as e.g. Mastodon, Misskey or Pleroma. ## Export of followed Contacts diff --git a/doc/faq-admin.md b/doc/faq-admin.md index 993a6c89ef..8f6897c0ad 100644 --- a/doc/faq-admin.md +++ b/doc/faq-admin.md @@ -3,11 +3,11 @@ Frequently Asked Questions (Admin) - FAQ * [Home](help) -* **[Can I configure multiple domains with the same code instance?](help/FAQ-admin#multiple)** -* **[Where can I find the source code of friendica, addons and themes?](help/FAQ-admin#sources)** -* **[I've changed the my email address now the admin panel is gone?](help/FAQ-admin#adminaccount1)** -* **[Can there be more then just one admin for a node?](help/FAQ-admin#adminaccount2)** -* **[The Database structure seems not to be updated. What can I do?](help/FAQ-admin#dbupdate)** +* **[Can I configure multiple domains with the same code instance?](help/faq-admin#multiple)** +* **[Where can I find the source code of friendica, addons and themes?](help/faq-admin#sources)** +* **[I've changed the my email address now the admin panel is gone?](help/faq-admin#adminaccount1)** +* **[Can there be more then just one admin for a node?](help/faq-admin#adminaccount2)** +* **[The Database structure seems not to be updated. What can I do?](help/faq-admin#dbupdate)** diff --git a/doc/faq.md b/doc/faq.md index 4e8d9b19eb..e269ee6caa 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -3,16 +3,16 @@ Frequently Asked Questions - FAQ * [Home](help) -* **[Where I can find help?](help/FAQ#help)** -* **[Why do I get warnings about certificates?](help/FAQ#ssl)** -* **[How can I upload images, files, links, videos and sound files to posts?](help/FAQ#upload)** -* **[Is it possible to have different avatars per profile?](help/FAQ#avatars)** -* **[How can I view Friendica in a certain language?](help/FAQ#language)** -* **[How do blocked, ignored, archived and hidden contacts behave?](help/FAQ#contacts)** -* **[What happens when an account is removed? Is it truly deleted?](help/FAQ#removed)** -* **[Can I subscribe to a hashtag?](help/FAQ#hashtag)** -* **[How to create an RSS feed of the stream?](help/FAQ#rss)** -* **[What friendica clients can I use?](help/FAQ#clients)** +* **[Where I can find help?](help/faq#help)** +* **[Why do I get warnings about certificates?](help/faq#ssl)** +* **[How can I upload images, files, links, videos and sound files to posts?](help/faq#upload)** +* **[Is it possible to have different avatars per profile?](help/faq#avatars)** +* **[How can I view Friendica in a certain language?](help/faq#language)** +* **[How do blocked, ignored, archived and hidden contacts behave?](help/faq#contacts)** +* **[What happens when an account is removed? Is it truly deleted?](help/faq#removed)** +* **[Can I subscribe to a hashtag?](help/faq#hashtag)** +* **[How to create an RSS feed of the stream?](help/faq#rss)** +* **[What friendica clients can I use?](help/faq#clients)** @@ -44,12 +44,12 @@ These warnings can have three reasons: 2. The server has a self-signed certificate (not recommended). 3. The certificate is expired. -We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/SSL).) +We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/ssl).) ### How can I upload images, files, links, videos and sound files to posts? -You can upload images from your computer using the [editor](help/Text_editor). +You can upload images from your computer using the [editor](help/text-editor). An overview of all uploaded images is listed at *yourpage.com/profile/profilename/photos*. On that page, you can also upload images directly and choose if your contacts will receive a message about this upload. @@ -104,7 +104,7 @@ When a certain language is forced, the language remains until session is closed. ### How do blocked, ignored, archived and hidden contacts behave? These are various categories of contacts that are restricted in some way. -Many of these types are related to [Safety](help/Safety). +Many of these types are related to [Safety](help/safety). ##### Blocked @@ -174,7 +174,7 @@ Example: Friendica Support ### What friendica clients can I use? -Friendica supports [Mastodon API](help/API-Mastodon) and [Twitter API | gnusocial](help/api). +Friendica supports [Mastodon API](help/api-mastodon) and [Twitter API | gnusocial](help/api). This means you can use some of the Mastodon and Twitter clients for Friendica. The available features are client specific and may differ. Clients dedicated to Friendica are marked in **bold**. diff --git a/doc/github.md b/doc/github.md index 24f2e6aa41..dc96bc420d 100644 --- a/doc/github.md +++ b/doc/github.md @@ -72,5 +72,5 @@ There is a console command called *typo* for this. $> php bin/console.php typo -Check out how to work with [our Vagrant](help/Vagrant) to save a lot of setup time! +Check out how to work with [our Vagrant](help/vagrant) to save a lot of setup time! diff --git a/doc/home.md b/doc/home.md index b8b3517a45..ead9d66d37 100644 --- a/doc/home.md +++ b/doc/home.md @@ -4,64 +4,64 @@ Help **User Manual** * General functions - first steps - * [Account Basics](help/Account-Basics) - * [New User Quick Start](help/Quick-Start-guide) - * [Creating posts](help/Text_editor) - * [BBCode tag reference](help/BBCode) - * [Comment, sort and delete posts](help/Text_comment) - * [Accesskey reference](help/Accesskeys) + * [Account Basics](help/account-basics) + * [New User Quick Start](help/quick-qtart-guide) + * [Creating posts](help/text-editor) + * [BBCode tag reference](help/bbcode) + * [Comment, sort and delete posts](help/text-comment) + * [Accesskey reference](help/access-keys) * [Events](help/events) * You and other users - * [Connectors](help/Connectors) - * [Making Friends](help/Making-Friends) - * [Safety](help/Safety) - * [Circles and Privacy](help/Circles-and-Privacy) - * [Tags and Mentions](help/Tags-and-Mentions) - * [Community Groups](help/Groups) - * [Channels](help/Channels) - * [Chats](help/Chats) + * [Connectors](help/connectors) + * [Making Friends](help/making-friends) + * [Safety](help/safety) + * [Circles and Privacy](help/circles-and-privacy) + * [Tags and Mentions](help/tags-and-mentions) + * [Community Groups](help/groups) + * [Channels](help/channels) + * [Chats](help/chats) * Further information - * [Move your account](help/Move-Account) - * [Export / Import of followed Contacts](help/Export-Import-Contacts) - * [Delete your account](help/Remove-Account) - * [Frequently asked questions (FAQ)](help/FAQ) + * [Move your account](help/move-account) + * [Export / Import of followed Contacts](help/export-import-contacts) + * [Delete your account](help/remove-account) + * [Frequently asked questions (FAQ)](help/faq) **Admin Manual** -* [Install](help/Install) -* [Update](help/Update) -* [Settings & Admin Panel](help/Settings) -* [Installing Connectors](help/Installing-Connectors) +* [Install](help/install) +* [Update](help/update) +* [Settings & Admin Panel](help/settings) +* [Installing Connectors](help/installing-connectors) * [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd) -* [Using SSL with Friendica](help/SSL) -* [Config values that can only be set in config/local.config.php](help/Config) -* [Improve Performance](help/Improve-Performance) -* [Migrate](help/Migrate) +* [Using SSL with Friendica](help/ssl) +* [Config values that can only be set in config/local.config.php](help/config) +* [Improve Performance](help/improve-performance) +* [Migrate](help/migrate) * [Administration Tools](help/tools) -* [Admin FAQ](help/FAQ-admin) +* [Admin FAQ](help/faq-admin) **Developer Manual** -* [Get started](help/Developers-Intro) +* [Get started](help/developers-intro) * Set up development environment - * [Help on GitHub](help/GitHub) - * [Help on Vagrant](help/Vagrant) - * [Bugs and Issues](help/Bugs-and-Issues) + * [Help on GitHub](help/github) + * [Help on Vagrant](help/vagrant) + * [Bugs and Issues](help/bugs-and-issues) * Code structure - * [Domain-Driven-Design](help/Developer-Domain-Driven-Design) - * [Addon Development](help/Addons) + * [Domain-Driven-Design](help/developer-domain-driven-design) + * [Addon Development](help/addons) * [Theme Development](help/themes) * [Smarty 3 Templates](help/smarty3-templates) - * [Storage backend addon](help/AddonStorageBackend) + * [Storage backend addon](help/addon-storage-backend) * How To * [Translate Friendica](help/translations) - * [Use Composer](help/Composer) - * [Move classes to `src`](help/Developer-How-To-Move-Classes-to-src) - * [Run tests](help/Tests) + * [Use Composer](help/composer) + * [Move classes to `src`](help/developer-how-to-move-classes-to-src) + * [Run tests](help/tests) * Reference * [API endpoints](help/api) * [Code (Doxygen generated - sets cookies)](doc/html/) - * [Protocol Documentation](help/Protocol) + * [Protocol Documentation](help/protocol) * [Database schema documentation](help/database) * [Class Autoloading](help/autoloader) diff --git a/doc/making-friends.md b/doc/making-friends.md index 85d4044cef..eb5109880a 100644 --- a/doc/making-friends.md +++ b/doc/making-friends.md @@ -113,4 +113,4 @@ These include: * Ignoring the contact, so that you will not see their posts * Blocking the contact from receiving your posts -For more information, see [Safety](help/Safety). +For more information, see [Safety](help/safety). diff --git a/doc/protocol.md b/doc/protocol.md index af0002472c..25e9cebdf9 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -9,7 +9,7 @@ Friendicas DFRN Protocol * [Document with the DFRN specification](spec/dfrn2.pdf) * [Schema of the contact request process](spec/dfrn2_contact_request.png) * [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png) -* [Description of the message flow](help/Message-Flow) +* [Description of the message flow](help/message-flow) ActivityStreams --- diff --git a/doc/quick-start-guide.md b/doc/quick-start-guide.md index ebcc6243f2..b31684dda2 100644 --- a/doc/quick-start-guide.md +++ b/doc/quick-start-guide.md @@ -18,7 +18,7 @@ Once you've finished writing your post, click on the padlock icon or permissions If you do not change anything, your post will be public. This means it will appear to anybody who views your profile, and in the community tab if your site has it enabled, as well as in the network tab of any of your contacts. -Play around with this a bit, then when you're ready to move on, we'll take a look at the Network Tab +Play around with this a bit, then when you're ready to move on, we'll take a look at the Network Tab diff --git a/doc/settings.md b/doc/settings.md index 08a512c2ab..7603a1b2bf 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -423,5 +423,5 @@ Say you have a subdirectory for tests and put Friendica into a further subdirect ## Other exceptions -Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/Config) section of the documentation. +Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/config) section of the documentation. diff --git a/doc/tags-and-mentions.md b/doc/tags-and-mentions.md index 8424b026cb..7c0e2e63bd 100644 --- a/doc/tags-and-mentions.md +++ b/doc/tags-and-mentions.md @@ -39,7 +39,7 @@ If you select a group from the ACL a !-mention will be added automatically to yo If you sort your contacts into circles, you cannot @-mention these circles. But you can select the circle in the access control when creating a new posting, to allow (or disallow) a certain circle of people to see the posting. -See [Circles and Privacy](help/Circles-and-Privacy) for more details about grouping your contacts. +See [Circles and Privacy](help/circles-and-privacy) for more details about grouping your contacts. **Topical Tags** diff --git a/doc/text-editor.md b/doc/text-editor.md index c20b9ac649..8c8cbfb81d 100644 --- a/doc/text-editor.md +++ b/doc/text-editor.md @@ -33,7 +33,7 @@ The Big Empty Textarea is where you write your new post. You can simply enter your text there and click the "Share" button, and your new post will be public on your profile page and shared to your contact. If plain text is not so exciting to you, Friendica understands BBCode to spice up your posts: bold, italic, images, links, lists.. -See [BBCode tags reference](help/BBCode) page to see all what you can do. +See [BBCode tags reference](help/bbcode) page to see all what you can do. The icons under the text area are there to help you to write posts quickly, but vary depending on the theme: @@ -70,7 +70,7 @@ These icons can change depending on the theme. Some examples:   -* how to [upload](help/FAQ#upload) files +* how to [upload](help/faq#upload) files

     

    **lock icon The Lock / Permissions** @@ -95,4 +95,4 @@ Click again on "show" or "don't show" to switch it off. You can search for contacts or circles with the search box. -See also [Circles and Privacy](help/Circles-and-Privacy) +See also [Circles and Privacy](help/circles-and-privacy) From 9cdda90168fbfe1cea26a304c1607709bd69c4a0 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 15:57:59 +0200 Subject: [PATCH 005/138] Docs: Update Help.php to point to the new name --- doc/account-basics.md | 2 +- doc/api-mastodon.md | 2 +- doc/install.md | 4 ++-- src/Module/Help.php | 36 ++++++++++++++++++------------------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/account-basics.md b/doc/account-basics.md index c5a0c088c6..515c0f6058 100644 --- a/doc/account-basics.md +++ b/doc/account-basics.md @@ -99,7 +99,7 @@ See Also * [Profiles](help/profiles) -* [Global Directory](help/making-friends#The+Directories) +* [Global Directory](help/making-friends#the+directories) * [Circles and Privacy](help/circles-and-privacy) diff --git a/doc/api-mastodon.md b/doc/api-mastodon.md index f41682869e..65fc5da1b5 100644 --- a/doc/api-mastodon.md +++ b/doc/api-mastodon.md @@ -7,7 +7,7 @@ Friendica provides the following endpoints defined in [the official Mastodon API reference](https://docs.joinmastodon.org/api/). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/api#authentication). ## Clients diff --git a/doc/install.md b/doc/install.md index 3c162d519b..62fc883340 100644 --- a/doc/install.md +++ b/doc/install.md @@ -12,7 +12,7 @@ This kind of functionality requires a bit more of the host system than the typic Not every PHP/MySQL hosting provider will be able to support Friendica. Many will. -But **please** review the [requirements](#Requirements) and confirm these with your hosting provider prior to installation. +But **please** review the [requirements](#requirements) and confirm these with your hosting provider prior to installation. ## Support If you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). @@ -123,7 +123,7 @@ Then use the following script using the password you just generated: Friendica needs the permission to create and delete fields and tables in its own database. -Please check the [troubleshooting](#Troubleshooting) section if running on MySQL 5.7.17 or newer. +Please check the [troubleshooting](#troubleshooting) section if running on MySQL 5.7.17 or newer. ### Option A: Run the installer diff --git a/src/Module/Help.php b/src/Module/Help.php index 59b40fd215..67645a7732 100644 --- a/src/Module/Help.php +++ b/src/Module/Help.php @@ -22,34 +22,34 @@ class Help extends BaseModule { Nav::setSelected('help'); - $text = ''; + $text = ''; $filename = ''; $config = DI::config(); - $lang = DI::session()->get('language', $config->get('system', 'language')); + $lang = DI::session()->get('language', $config->get('system', 'language')); // @TODO: Replace with parameter from router if (DI::args()->getArgc() > 1) { $path = ''; // looping through the argv keys bigger than 0 to build // a path relative to /help - for ($x = 1; $x < DI::args()->getArgc(); $x ++) { + for ($x = 1; $x < DI::args()->getArgc(); $x++) { if (strlen($path)) { $path .= '/'; } $path .= DI::args()->get($x); } - $title = basename($path); - $filename = $path; - $text = self::loadDocFile('doc/' . $path . '.md', $lang); + $title = basename($path); + $filename = $path; + $text = self::loadDocFile('doc/' . $path . '.md', $lang); DI::page()['title'] = DI::l10n()->t('Help:') . ' ' . str_replace('-', ' ', $title); } - $home = self::loadDocFile('doc/Home.md', $lang); + $home = self::loadDocFile('doc/home.md', $lang); if (!$text) { - $text = $home; - $filename = "Home"; + $text = $home; + $filename = "home"; DI::page()['title'] = DI::l10n()->t('Help'); } else { DI::page()['aside'] = Markdown::convert($home, false); @@ -61,17 +61,17 @@ class Help extends BaseModule $html = Markdown::convert($text, false); - if ($filename !== "Home") { + if ($filename !== "home") { // create TOC but not for home - $lines = explode("\n", $html); - $toc = "

    TOC

      "; + $lines = explode("\n", $html); + $toc = "

      TOC

        "; $lastLevel = 1; - $idNum = [0, 0, 0, 0, 0, 0, 0]; + $idNum = [0, 0, 0, 0, 0, 0, 0]; foreach ($lines as &$line) { $matches = []; if (preg_match('#([^<]+?)#i', $line, $matches)) { - $level = $matches[1]; - $anchor = urlencode($matches[2]); + $level = $matches[1]; + $anchor = strtolower(urlencode($matches[2])); if ($level < $lastLevel) { for ($k = $level; $k < $lastLevel; $k++) { $toc .= "
      "; @@ -86,11 +86,11 @@ class Help extends BaseModule $toc .= "
      • "; } - $idNum[$level] ++; + $idNum[$level]++; $href = "help/{$filename}#{$anchor}"; $toc .= "
      • " . strip_tags($line) . "
      • "; - $id = implode("_", array_slice($idNum, 1, $level)); + $id = implode("_", array_slice($idNum, 1, $level)); $line = "" . $line; $line = "" . $line; @@ -113,7 +113,7 @@ class Help extends BaseModule private static function loadDocFile($fileName, $lang = 'en') { $baseName = basename($fileName); - $dirName = dirname($fileName); + $dirName = dirname($fileName); if (file_exists("$dirName/$lang/$baseName")) { return file_get_contents("$dirName/$lang/$baseName"); } From 3113f0bcbac2928e976139c933cc45b2e25dc088 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 16:18:36 +0200 Subject: [PATCH 006/138] Docs: Remove dysfunctional internal links from installation guide --- doc/install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install.md b/doc/install.md index 62fc883340..7ad38c78ca 100644 --- a/doc/install.md +++ b/doc/install.md @@ -12,7 +12,7 @@ This kind of functionality requires a bit more of the host system than the typic Not every PHP/MySQL hosting provider will be able to support Friendica. Many will. -But **please** review the [requirements](#requirements) and confirm these with your hosting provider prior to installation. +But **please** review the requirements below and confirm these with your hosting provider prior to installation. ## Support If you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). @@ -123,7 +123,7 @@ Then use the following script using the password you just generated: Friendica needs the permission to create and delete fields and tables in its own database. -Please check the [troubleshooting](#troubleshooting) section if running on MySQL 5.7.17 or newer. +Please check the Troubleshooting section below if running on MySQL 5.7.17 or newer. ### Option A: Run the installer From 6a451b49f61012b693c541af9e7b38ed3c43c6e6 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sat, 11 Oct 2025 23:07:53 +0200 Subject: [PATCH 007/138] Allow user creation by mods/admins when invitation_only is enabled --- src/Model/User.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Model/User.php b/src/Model/User.php index 5195fb77a3..7923690ca6 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -1178,9 +1178,10 @@ class User { $return = ['user' => null, 'password' => '']; - $using_invites = DI::config()->get('system', 'invitation_only'); + $using_invites = DI::config()->get('system', 'invitation_only', false); + $ignore_invites = (array_key_exists('ignore_invites', $data) && is_bool($data['ignore_invites'])) ? $data['ignore_invites'] : false; + $invite_id = (array_key_exists('invite_id', $data) && is_string($data['invite_id'])) ? trim($data['invite_id']) : ''; - $invite_id = !empty($data['invite_id']) ? trim($data['invite_id']) : ''; $username = !empty($data['username']) ? trim($data['username']) : ''; $nickname = !empty($data['nickname']) ? trim($data['nickname']) : ''; $email = !empty($data['email']) ? trim($data['email']) : ''; @@ -1201,7 +1202,9 @@ class User $password = $password1; } - if ($using_invites) { + + // Users created by the console or from the moderation page ignore invites + if ($using_invites && !$ignore_invites) { if (!$invite_id) { throw new Exception(DI::l10n()->t('An invitation is required.')); } @@ -1620,12 +1623,13 @@ class User } $result = self::create([ - 'username' => $name, - 'email' => $email, - 'nickname' => $nick, - 'verified' => 1, - 'language' => $lang, - 'photo' => $avatar + 'ignore_invites' => true, + 'username' => $name, + 'email' => $email, + 'nickname' => $nick, + 'verified' => 1, + 'language' => $lang, + 'photo' => $avatar ]); $user = $result['user']; From a46450a57576d18f0b89eb1c99b95e9c88d1c8c2 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 16:44:25 +0200 Subject: [PATCH 008/138] Docs: Final cleanup --- ...-start-andfinally.md => quick-start-finally.md} | 0 ...andpages.md => quick-start-groups-and-pages.md} | 6 +++--- ...riends.md => quick-start-making-new-friends.md} | 4 ++-- doc/de/quick-start-network.md | 14 +++++++------- doc/install.md | 2 +- ...-start-andfinally.md => quick-start-finally.md} | 0 ...andpages.md => quick-start-groups-and-pages.md} | 4 ++-- ...riends.md => quick-start-making-new-friends.md} | 4 ++-- doc/quick-start-network.md | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) rename doc/de/{quick-start-andfinally.md => quick-start-finally.md} (100%) rename doc/de/{quick-start-groupsandpages.md => quick-start-groups-and-pages.md} (86%) rename doc/de/{quick-start-makingnewfriends.md => quick-start-making-new-friends.md} (86%) rename doc/{quick-start-andfinally.md => quick-start-finally.md} (100%) rename doc/{quick-start-groupsandpages.md => quick-start-groups-and-pages.md} (81%) rename doc/{quick-start-makingnewfriends.md => quick-start-making-new-friends.md} (79%) diff --git a/doc/de/quick-start-andfinally.md b/doc/de/quick-start-finally.md similarity index 100% rename from doc/de/quick-start-andfinally.md rename to doc/de/quick-start-finally.md diff --git a/doc/de/quick-start-groupsandpages.md b/doc/de/quick-start-groups-and-pages.md similarity index 86% rename from doc/de/quick-start-groupsandpages.md rename to doc/de/quick-start-groups-and-pages.md index d4ea55d3d0..44079fd777 100644 --- a/doc/de/quick-start-groupsandpages.md +++ b/doc/de/quick-start-groups-and-pages.md @@ -6,9 +6,9 @@ Gruppen und Seiten Hier siehst Du das globale Verzeichnis. Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. -Auf dieser Seite findest Du eine Zusammenstellung von Gruppen. +Auf dieser Seite findest Du eine Zusammenstellung von Gruppen. Gruppen sind keine realen Personen. -Sich mit diesen zu verbinden ist, als wenn man jemanden auf Facebook "liked" ("gefällt mir") oder wenn man sich in einem Forum anmeldet. +Sich mit diesen zu verbinden ist, als wenn man jemanden auf Facebook "liked" ("gefällt mir") oder wenn man sich in einem Forum anmeldet. Du musst nicht unsicher sein, ob Du jemandem zu nahe trittst, wenn Du Dich so ohne weiteres mit einer Gruppe verbindest; es handelt sich eben nicht um reale Personen. Wenn Du Dich mit einer Gruppe verbindest, erscheinen alle Nachrichten der Gruppe in Deinem "Netzwerk"-Tab. @@ -19,7 +19,7 @@ Suche Dir einfach eine Gruppe und füge sie so hinzu, wie Du auch normale Freund Es gibt eine Menge Gruppen. Solltest Du beim Stöbern durch die vielen Gruppen nicht wieder hierher zurück finden, so nutze einfach den Link oben auf dieser Seite. -Wenn Du einige Gruppen hinzugefügt hast, gehe weiter zum nächsten Schritt. +Wenn Du einige Gruppen hinzugefügt hast, gehe weiter zum nächsten Schritt. diff --git a/doc/de/quick-start-makingnewfriends.md b/doc/de/quick-start-making-new-friends.md similarity index 86% rename from doc/de/quick-start-makingnewfriends.md rename to doc/de/quick-start-making-new-friends.md index 701fba505f..24fcbcc5dc 100644 --- a/doc/de/quick-start-makingnewfriends.md +++ b/doc/de/quick-start-making-new-friends.md @@ -4,7 +4,7 @@ Neue Freunde finden * [Zur Startseite der Hilfe](help) Hier siehst Du die Kontaktvorschläge. -Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. +Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. Diese Seite funktioniert in etwa wie die Seite für Kontaktvorschläge in Facebook. Jeder auf dieser Liste hat zugestimmt, als Kontaktvorschlag zu erscheinen. @@ -21,7 +21,7 @@ Jetzt, nachdem Du jemanden hinzugefügt hast, weißt Du vielleicht nicht mehr, w Klicke einfach auf den Link oben auf dieser Seite und Du gelangst zur Seite mit den Kontaktvorschlägen zurück, um weitere Personen hinzuzufügen. Du willst nicht einfach Personen hinzufügen, die du nicht kennst? -Kein Problem - an dieser Stelle kommen wir zu den Gruppen und Seiten. +Kein Problem - an dieser Stelle kommen wir zu den Gruppen und Seiten. diff --git a/doc/de/quick-start-network.md b/doc/de/quick-start-network.md index 0c6f828355..c810010809 100644 --- a/doc/de/quick-start-network.md +++ b/doc/de/quick-start-network.md @@ -3,17 +3,17 @@ Deine "Netzwerk"-Seite * [Zur Startseite der Hilfe](help) -Dies ist Dein "Netzwerk"-Tab. +Dies ist Dein "Netzwerk"-Tab. Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken, um wieder hierher zu kommen. -Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. -Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. -Wenn Du neu bist, siehst Du hier noch nichts, falls Du an Deinem Status im letzten Schritt noch nichts geändert haben solltest. -Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträge. +Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. +Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. +Wenn Du neu bist, siehst Du hier noch nichts, falls Du an Deinem Status im letzten Schritt noch nichts geändert haben solltest. +Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträge. Du kannst ihre Beiträge von hier aus kommentieren, mitteilen, dass Du den Beitrag magst oder ablehnst (Daumen hoch, Daumen runter) oder die Profile durch einen Klick auf deren Namen besuchen und dort auf deren "Pinnwand" ("Wall") Nachrichten schreiben. -Nun wollen wir diese Seite mit Inhalt füllen. -Der erste Schritt ist es, Leute zu Deinem Account hinzuzufügen. +Nun wollen wir diese Seite mit Inhalt füllen. +Der erste Schritt ist es, Leute zu Deinem Account hinzuzufügen. diff --git a/doc/install.md b/doc/install.md index 7ad38c78ca..54332a674b 100644 --- a/doc/install.md +++ b/doc/install.md @@ -303,7 +303,7 @@ This could be achieved by a cronjob. ### (RECOMMENDED) Logging & Log Rotation At this point it is recommended that you set up logging and logrotation. -To do so please visit [Settings](help/Settings) and search the 'Logs' section for more information. +To do so please visit [Settings](help/settings) and search the 'Logs' section for more information. ### (RECOMMENDED) Set up a backup plan diff --git a/doc/quick-start-andfinally.md b/doc/quick-start-finally.md similarity index 100% rename from doc/quick-start-andfinally.md rename to doc/quick-start-finally.md diff --git a/doc/quick-start-groupsandpages.md b/doc/quick-start-groups-and-pages.md similarity index 81% rename from doc/quick-start-groupsandpages.md rename to doc/quick-start-groups-and-pages.md index c9a27c6f1c..0fd27b5338 100644 --- a/doc/quick-start-groupsandpages.md +++ b/doc/quick-start-groups-and-pages.md @@ -1,5 +1,5 @@ This is the global directory. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can click this link to bring yourself back here. On this page, you'll find a collection of groups. Groups are not real people. @@ -13,7 +13,7 @@ Simply find a group you're interested in, and connect to it the same way you did There are a lot of groups, and you're likely to get lost. Remember the link at the top of this page will bring you back here. -Once you've added some groups, move on to the next section. +Once you've added some groups, move on to the next section. diff --git a/doc/quick-start-makingnewfriends.md b/doc/quick-start-making-new-friends.md similarity index 79% rename from doc/quick-start-makingnewfriends.md rename to doc/quick-start-making-new-friends.md index d642905698..4971d3dd1d 100644 --- a/doc/quick-start-makingnewfriends.md +++ b/doc/quick-start-making-new-friends.md @@ -1,5 +1,5 @@ This is your Suggested Friends page. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can click this link to bring yourself back here. This is a bit like the Friend Suggestions page of Facebook. Everybody on this list has agreed that they may be suggested as a friend. @@ -14,7 +14,7 @@ Now you've added one, you're probably lost. Click the link at the top of this page to go back to the suggested friends list and add some more. Feel uncomfortable adding people you don't know? -Don't worry - that's where Groups and Pages come in! +Don't worry - that's where Groups and Pages come in! diff --git a/doc/quick-start-network.md b/doc/quick-start-network.md index e0c138d2bd..3c97c23c88 100644 --- a/doc/quick-start-network.md +++ b/doc/quick-start-network.md @@ -1,5 +1,5 @@ This is your Network Tab. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can click this link to bring yourself back here. This is a bit like the Newsfeed at Facebook or the Stream at Diaspora. It's where all the posts from your contacts, groups, and feeds will appear. @@ -7,7 +7,7 @@ If you're new, you won't see anything in this page, unless you posted your statu If you've already added a few friends, you'll be able to see their posts. Here, you can comment, like, or dislike posts, or click on somebody's name to visit their profile page where you can write on their wall. -Now we need to fill it up, the first step, is to make some new friends. +Now we need to fill it up, the first step, is to make some new friends. From 8ad361d2ef3148ceeb249925740efdf5a5486b9a Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 17:33:18 +0200 Subject: [PATCH 009/138] Move spec/ to doc/spec/protocol --- {spec => doc/spec/protocol}/dfrn-snap2.jpg | Bin {spec => doc/spec/protocol}/dfrn2.odt | Bin {spec => doc/spec/protocol}/dfrn2.pdf | Bin .../spec/protocol}/dfrn2_contact_confirmation.png | Bin .../spec/protocol}/dfrn2_contact_confirmation.svg | 0 .../spec/protocol}/dfrn2_contact_request.png | Bin .../spec/protocol}/dfrn2_contact_request.svg | 0 {spec => doc/spec/protocol}/zot-2012.txt | 0 {spec => doc/spec/protocol}/zot.txt | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {spec => doc/spec/protocol}/dfrn-snap2.jpg (100%) rename {spec => doc/spec/protocol}/dfrn2.odt (100%) rename {spec => doc/spec/protocol}/dfrn2.pdf (100%) rename {spec => doc/spec/protocol}/dfrn2_contact_confirmation.png (100%) rename {spec => doc/spec/protocol}/dfrn2_contact_confirmation.svg (100%) rename {spec => doc/spec/protocol}/dfrn2_contact_request.png (100%) rename {spec => doc/spec/protocol}/dfrn2_contact_request.svg (100%) rename {spec => doc/spec/protocol}/zot-2012.txt (100%) rename {spec => doc/spec/protocol}/zot.txt (100%) diff --git a/spec/dfrn-snap2.jpg b/doc/spec/protocol/dfrn-snap2.jpg similarity index 100% rename from spec/dfrn-snap2.jpg rename to doc/spec/protocol/dfrn-snap2.jpg diff --git a/spec/dfrn2.odt b/doc/spec/protocol/dfrn2.odt similarity index 100% rename from spec/dfrn2.odt rename to doc/spec/protocol/dfrn2.odt diff --git a/spec/dfrn2.pdf b/doc/spec/protocol/dfrn2.pdf similarity index 100% rename from spec/dfrn2.pdf rename to doc/spec/protocol/dfrn2.pdf diff --git a/spec/dfrn2_contact_confirmation.png b/doc/spec/protocol/dfrn2_contact_confirmation.png similarity index 100% rename from spec/dfrn2_contact_confirmation.png rename to doc/spec/protocol/dfrn2_contact_confirmation.png diff --git a/spec/dfrn2_contact_confirmation.svg b/doc/spec/protocol/dfrn2_contact_confirmation.svg similarity index 100% rename from spec/dfrn2_contact_confirmation.svg rename to doc/spec/protocol/dfrn2_contact_confirmation.svg diff --git a/spec/dfrn2_contact_request.png b/doc/spec/protocol/dfrn2_contact_request.png similarity index 100% rename from spec/dfrn2_contact_request.png rename to doc/spec/protocol/dfrn2_contact_request.png diff --git a/spec/dfrn2_contact_request.svg b/doc/spec/protocol/dfrn2_contact_request.svg similarity index 100% rename from spec/dfrn2_contact_request.svg rename to doc/spec/protocol/dfrn2_contact_request.svg diff --git a/spec/zot-2012.txt b/doc/spec/protocol/zot-2012.txt similarity index 100% rename from spec/zot-2012.txt rename to doc/spec/protocol/zot-2012.txt diff --git a/spec/zot.txt b/doc/spec/protocol/zot.txt similarity index 100% rename from spec/zot.txt rename to doc/spec/protocol/zot.txt From 64a21f212ba3c867208a695900fa2e247c11dd10 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Sun, 12 Oct 2025 18:58:26 +0200 Subject: [PATCH 010/138] Update outside references to docs --- src/Module/Admin/Summary.php | 6 +++--- src/Module/Settings/Channels.php | 2 +- view/templates/welcome.tpl | 4 ++-- view/theme/vier/theme.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 282c15e4bc..0635b5cbee 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -91,11 +91,11 @@ class Summary extends BaseAdmin // Legacy config file warning if (file_exists('.htconfig.php')) { - $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from .htconfig.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/Config'); + $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from .htconfig.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/config'); } if (file_exists('config/local.ini.php')) { - $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/Config'); + $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/config'); } // Check server vitality @@ -105,7 +105,7 @@ class Summary extends BaseAdmin '%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', $well_known, $well_known, - DI::baseUrl() . '/help/Install' + DI::baseUrl() . '/help/install' ); } diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index ba553d93e7..47a7faecd0 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -207,7 +207,7 @@ class Channels extends BaseSettings 'exclude_tags' => ["new_exclude_tags", $this->t("Exclude Tags"), '', $exclude_tags_translation], 'min_size' => ["new_min_size", $this->t("Minimum Size"), '', $this->t('Minimum post size. Leave empty for no minimum size. The size is calculated without links, attached posts, mentions or hashtags.')], 'max_size' => ["new_max_size", $this->t("Maximum Size"), '', $this->t('Maximum post size. Leave empty for no maximum size. The size is calculated without links, attached posts, mentions or hashtags.')], - 'text_search' => ["new_text_search", $this->t("Full Text Search"), '', $this->t('Search terms for the body, supports the "boolean mode" operators from MariaDB. See the help for a complete list of operators and additional keywords: %s', 'help/Channels')], + 'text_search' => ["new_text_search", $this->t("Full Text Search"), '', $this->t('Search terms for the body, supports the "boolean mode" operators from MariaDB. See the help for a complete list of operators and additional keywords: %s', 'help/channels')], 'image' => ['new_image', $this->t("Images"), false, $this->t("Check to display images in the channel.")], 'video' => ["new_video", $this->t("Videos"), false, $this->t("Check to display videos in the channel.")], 'audio' => ["new_audio", $this->t("Audio"), false, $this->t("Check to display audio in the channel.")], diff --git a/view/templates/welcome.tpl b/view/templates/welcome.tpl index 64090ab02b..f8f4141a3f 100644 --- a/view/templates/welcome.tpl +++ b/view/templates/welcome.tpl @@ -12,7 +12,7 @@

        {{$started nofilter}}

        @@ -70,7 +70,7 @@ {{if $newuser_private}}
      • - {{$private_link}}
        + {{$private_link}}
        {{$private_txt nofilter}}
      • {{/if}} diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php index c70f55ecc1..4b26100c0f 100644 --- a/view/theme/vier/theme.php +++ b/view/theme/vier/theme.php @@ -218,7 +218,7 @@ function vier_community_info() $r[$index]["url"] = Contact::magicLink($helper["url"]); } - $r[] = ["url" => "help/Quick-Start-guide", "name" => DI::l10n()->t("Quick Start")]; + $r[] = ["url" => "help/quick-start-guide", "name" => DI::l10n()->t("Quick Start")]; $tpl = Renderer::getMarkupTemplate('ch_helpers.tpl'); From 7404b3a2300d69a2f63c5de934da2cc6ad93e580 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Mon, 13 Oct 2025 21:05:27 +0200 Subject: [PATCH 011/138] Docs updates: Restructuring, code blocks, quick start guide markdown links --- doc/access-keys.md | 43 ++-- doc/account-basics.md | 39 +-- doc/addon-storage-backend.md | 3 +- doc/addons.md | 15 +- doc/{ => assets}/img/acl_win.png | Bin doc/{ => assets}/img/camera.png | Bin doc/{ => assets}/img/chain.png | Bin doc/{ => assets}/img/diabook.png | Bin doc/{ => assets}/img/editor_frio.png | Bin doc/{ => assets}/img/editor_vier.png | Bin .../img/friendica_rich_editor.png | Bin doc/{ => assets}/img/frio_location.png | Bin doc/{ => assets}/img/globe.png | Bin doc/{ => assets}/img/lock.png | Bin doc/{ => assets}/img/mic.png | Bin doc/{ => assets}/img/padlock.png | Bin doc/{ => assets}/img/paper_clip.png | Bin doc/{ => assets}/img/post_categorize.png | Bin doc/{ => assets}/img/post_choose.png | Bin doc/{ => assets}/img/post_delete.png | Bin doc/{ => assets}/img/post_link.png | Bin doc/{ => assets}/img/post_mark.png | Bin doc/{ => assets}/img/post_share.png | Bin doc/{ => assets}/img/post_tag.png | Bin doc/{ => assets}/img/post_thumbs_down.png | Bin doc/{ => assets}/img/post_thumbs_up.png | Bin doc/{ => assets}/img/posts_define.png | Bin doc/{ => assets}/img/video.png | Bin doc/{ => assets}/img/vier_icons.png | Bin doc/autoloader.md | 9 +- doc/bbcode.md | 105 ++++---- doc/bugs-and-issues.md | 5 +- doc/channels.md | 12 +- doc/chats.md | 26 +- doc/circles-and-privacy.md | 22 +- doc/composer.md | 5 +- doc/config.md | 3 +- doc/connectors.md | 30 +-- doc/de/account-basics.md | 21 +- doc/de/addons.md | 21 +- doc/de/bbcode.md | 100 ++++---- doc/de/bugs-and-issues.md | 15 +- doc/de/channels.md | 12 +- doc/de/chats.md | 3 +- doc/de/circles-and-privacy.md | 16 +- doc/de/connectors.md | 37 ++- doc/de/developers.md | 11 +- doc/de/events.md | 1 - doc/de/export-import-contacts.md | 4 +- doc/de/faq-admin.md | 13 +- doc/de/faq.md | 71 +++--- doc/de/groups.md | 3 +- doc/de/guide.md | 27 +- doc/de/home.md | 5 +- doc/de/improve-performance.md | 24 +- doc/de/install.md | 154 ++++++------ doc/de/installing-connectors.md | 6 +- doc/de/making-friends.md | 13 +- doc/de/message-flow.md | 55 ++-- doc/de/move-account.md | 14 +- doc/de/quick-start-finally.md | 18 -- doc/de/quick-start/finally.md | 14 ++ .../groups-and-pages.md} | 7 +- .../guide.md} | 17 +- .../making-new-friends.md} | 9 +- .../network.md} | 9 +- doc/de/readme.md | 7 +- doc/de/remove-account.md | 11 +- doc/de/settings.md | 50 ++-- doc/de/ssl.md | 40 +-- doc/de/tags-and-mentions.md | 3 +- doc/de/text-comment.md | 29 ++- doc/de/text-editor.md | 23 +- doc/developer-domain-driven-design.md | 3 +- doc/developer-how-to-move-classes-to-src.md | 7 +- doc/developers-intro.md | 2 +- doc/events.md | 4 +- doc/faq-admin.md | 18 +- doc/faq.md | 47 ++-- doc/github.md | 23 +- doc/groups.md | 15 +- doc/home.md | 17 +- doc/improve-performance.md | 28 +-- doc/install-ejabberd.md | 46 ++-- doc/install.md | 235 ++++++++++-------- doc/installing-connectors.md | 9 +- doc/keyboard-shortcuts.md | 6 +- doc/making-friends.md | 32 ++- doc/message-flow.md | 21 +- doc/migrate.md | 8 +- doc/move-account.md | 10 +- doc/protocol.md | 13 +- doc/quick-start-finally.md | 14 -- doc/quick-start/finally.md | 12 + .../groups-and-pages.md} | 6 +- .../guide.md} | 4 +- .../making-new-friends.md} | 6 +- .../network.md} | 6 +- doc/remove-account.md | 3 +- doc/safety.md | 18 +- doc/settings.md | 56 +++-- doc/smarty3-templates.md | 33 +-- doc/ssl.md | 31 +-- doc/stats.md | 3 +- doc/strategy-hooks.md | 3 +- doc/tags-and-mentions.md | 9 +- doc/text-comment.md | 21 +- doc/text-editor.md | 29 ++- doc/tools.md | 49 ++-- doc/translations.md | 30 +-- doc/update.md | 27 +- doc/vagrant.md | 29 +-- src/Module/Help.php | 7 + view/templates/welcome.tpl | 2 +- view/theme/vier/theme.php | 2 +- 115 files changed, 1025 insertions(+), 1099 deletions(-) rename doc/{ => assets}/img/acl_win.png (100%) rename doc/{ => assets}/img/camera.png (100%) rename doc/{ => assets}/img/chain.png (100%) rename doc/{ => assets}/img/diabook.png (100%) rename doc/{ => assets}/img/editor_frio.png (100%) rename doc/{ => assets}/img/editor_vier.png (100%) rename doc/{ => assets}/img/friendica_rich_editor.png (100%) rename doc/{ => assets}/img/frio_location.png (100%) rename doc/{ => assets}/img/globe.png (100%) rename doc/{ => assets}/img/lock.png (100%) rename doc/{ => assets}/img/mic.png (100%) rename doc/{ => assets}/img/padlock.png (100%) rename doc/{ => assets}/img/paper_clip.png (100%) rename doc/{ => assets}/img/post_categorize.png (100%) rename doc/{ => assets}/img/post_choose.png (100%) rename doc/{ => assets}/img/post_delete.png (100%) rename doc/{ => assets}/img/post_link.png (100%) rename doc/{ => assets}/img/post_mark.png (100%) rename doc/{ => assets}/img/post_share.png (100%) rename doc/{ => assets}/img/post_tag.png (100%) rename doc/{ => assets}/img/post_thumbs_down.png (100%) rename doc/{ => assets}/img/post_thumbs_up.png (100%) rename doc/{ => assets}/img/posts_define.png (100%) rename doc/{ => assets}/img/video.png (100%) rename doc/{ => assets}/img/vier_icons.png (100%) delete mode 100644 doc/de/quick-start-finally.md create mode 100644 doc/de/quick-start/finally.md rename doc/de/{quick-start-groups-and-pages.md => quick-start/groups-and-pages.md} (89%) rename doc/de/{quick-start-guide.md => quick-start/guide.md} (88%) rename doc/de/{quick-start-making-new-friends.md => quick-start/making-new-friends.md} (78%) rename doc/de/{quick-start-network.md => quick-start/network.md} (76%) delete mode 100644 doc/quick-start-finally.md create mode 100644 doc/quick-start/finally.md rename doc/{quick-start-groups-and-pages.md => quick-start/groups-and-pages.md} (81%) rename doc/{quick-start-guide.md => quick-start/guide.md} (95%) rename doc/{quick-start-making-new-friends.md => quick-start/making-new-friends.md} (79%) rename doc/{quick-start-network.md => quick-start/network.md} (69%) diff --git a/doc/access-keys.md b/doc/access-keys.md index ed0c55f7f5..e32eeb1fe9 100644 --- a/doc/access-keys.md +++ b/doc/access-keys.md @@ -1,5 +1,4 @@ -Accesskeys reference -======================= +# Access keys reference * [Home](help) @@ -12,8 +11,8 @@ For example, for moving to profile page in Firefox, press these three keys simul [Shift] [Alt] [p] -General -------- +## General + * p - Profile * n - Network * l - Channel @@ -24,13 +23,13 @@ General * f - Notifications * u - User menu -../community --------- +## ../community + * l - Local community * g - Global community -../channel --------- +## ../channel + * y - for you * f - followers * r - sharers of sharers @@ -42,8 +41,8 @@ General * g - Posts in your language * o - Hot posts in your language -../profile --------- +## ../profile + * m - Status Messages and Posts * r - Profile Details * h - Photo Albums @@ -53,8 +52,8 @@ General * o - Scheduled Posts * k - View Contacts -../contacts (contact list) ---------- +## ../contacts (contact list) + * g - Suggestions * l - Show all Contacts * o - Only show unblocked contacts @@ -64,8 +63,8 @@ General * h - Only show hidden contacts * e - Edit contact circles -../contact (single contact view) -------------------------------- +## ../contact (single contact view) + * m - Status messages * p - Posts and Comments * d - Media @@ -73,12 +72,12 @@ General * t - Contacts * r - Advanced -../message --------- +## ../message + * m - New message -../network --------- +## ../network + * e - Sort by Comment Date * t - Sort by Receipt Date * q - Sort by Creation Date @@ -86,16 +85,16 @@ General * w - New posts * m - Favourite Posts -../notifications --------------- +## ../notifications + * y - System * w - Network * r - Personal * h - Home * i - Introductions -../settings ---------- +## ../settings + * o - Account * 2 - Two-factor authentication * p - Profiles diff --git a/doc/account-basics.md b/doc/account-basics.md index 515c0f6058..f767b6f59e 100644 --- a/doc/account-basics.md +++ b/doc/account-basics.md @@ -1,10 +1,8 @@ -Account Basics -============== +# Account Basics * [Home](help) -Registration ---- +## Registration Not all Friendica sites allow open registration. If registration is allowed, you will see a "Register" link immediately below the login prompt on the site's home page. @@ -46,14 +44,13 @@ It must contain only US-ASCII text characters and numbers, and must also start w It also must be unique on this system. This is used in many places to identify your account, and once set it cannot be changed. - ### Directory Publishing The registration form also allows you to choose whether or not to list your account in the online directory of your node. This is like a "phone book" and you may choose to be unlisted. We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you. If you choose 'No', you will essentially be invisible and have few opportunities for interaction. -Whichever you choose, this can be changed any time from your Settings page after you login. +Whichever you choose, this can be changed any time from your Settings page after you log in. ### Register @@ -61,8 +58,7 @@ Once you have provided the necessary details, click the 'Register' button. An email will be sent to you providing your account login details. Please check your email (including spam folders) for your registration details and initial password. -Login Page ---- +## Login Page On the 'Login' page, please enter your login information that was provided during registration. You may use either your nickname or email address as a Login Name. @@ -76,34 +72,25 @@ Otherwise, enter your password. This will have been initially provided in your registration email message. Your password is case-sensitive, so please check your 'Caps Lock' key if you are having difficulty logging in. -Changing Your Password ---- +## Changing Your Password After your first login, please visit the 'Settings' page from the top menu bar and change your password to something that you will remember. -Getting Started ---- +## Getting Started A link with ['Tips for New Members'](newmember) will show up on your network and home pages for two weeks providing key information for getting started. -Retrieving Personal Data ---- +## Retrieving Personal Data You can export a copy of your personal data in JSON format from the "Export personal data" link at the top of your settings page. You need this file to relocate your Friendica account to another node. This might be necessary, e.g. if your node suffers a severe hardware problem and is not recoverable. -See Also ---- - -* [Profiles](help/profiles) - -* [Global Directory](help/making-friends#the+directories) - -* [Circles and Privacy](help/circles-and-privacy) - -* [Move Account](help/move-account) - -* [Remove Account](help/remove-account) +## See Also +- [Profiles](help/profiles) +- [Global Directory](help/making-friends#the+directories) +- [Circles and Privacy](help/circles-and-privacy) +- [Move Account](help/move-account) +- [Remove Account](help/remove-account) diff --git a/doc/addon-storage-backend.md b/doc/addon-storage-backend.md index 5053b641cb..b6023c5518 100644 --- a/doc/addon-storage-backend.md +++ b/doc/addon-storage-backend.md @@ -1,5 +1,4 @@ -Friendica Storage Backend Addon development -=========================================== +# Friendica Storage Backend Addon development * [Home](help) diff --git a/doc/addons.md b/doc/addons.md index 84586f91e2..9d0fddf5e9 100644 --- a/doc/addons.md +++ b/doc/addons.md @@ -1,5 +1,4 @@ -Friendica Addon development -============== +# Friendica Addon development * [Home](help) @@ -144,7 +143,7 @@ No additional data is provided. ## Modules Addons may also act as "modules" and intercept all page requests for a given URL path. -In order for a addon to act as a module it needs to declare an empty function `_module()`. +In order for an addon to act as a module it needs to declare an empty function `_module()`. If this function exists, you will now receive all page requests for `https://my.web.site/` - with any number of URL components as additional arguments. These are parsed into the `App\Arguments` object. @@ -560,7 +559,7 @@ For `select`, **field** is: Called just before dispatching the router. Hook data is a `\FastRoute\RouterCollector` object that should be used to add addon routes pointing to classes. -**Notice**: The class whose name is provided in the route handler must be reachable via auto-loader. +**Notice**: The class whose name is provided in the route handler must be reachable via autoloader. ### probe_detect @@ -618,7 +617,7 @@ Called when unfollowing a remote contact on a non-native network (like Bluesky) Hook data: - **contact** (input): the target public contact (uid = 0) array. - **uid** (input): the id of the source local user. -- **result** (output): wether the unfollowing is successful or not. +- **result** (output): whether the unfollowing is successful or not. ### revoke_follow @@ -627,7 +626,7 @@ Called when making a remote contact on a non-native network (like Bluesky) unfol Hook data: - **contact** (input): the target public contact (uid = 0) array. - **uid** (input): the id of the source local user. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### block @@ -636,7 +635,7 @@ Called when blocking a remote contact on a non-native network (like Bluesky). Hook data: - **contact** (input): the remote contact (uid = 0) array. - **uid** (input): the user id to issue the block for. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### unblock @@ -645,7 +644,7 @@ Called when unblocking a remote contact on a non-native network (like Bluesky). Hook data: - **contact** (input): the remote contact (uid = 0) array. - **uid** (input): the user id to revoke the block for. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### support_probe diff --git a/doc/img/acl_win.png b/doc/assets/img/acl_win.png similarity index 100% rename from doc/img/acl_win.png rename to doc/assets/img/acl_win.png diff --git a/doc/img/camera.png b/doc/assets/img/camera.png similarity index 100% rename from doc/img/camera.png rename to doc/assets/img/camera.png diff --git a/doc/img/chain.png b/doc/assets/img/chain.png similarity index 100% rename from doc/img/chain.png rename to doc/assets/img/chain.png diff --git a/doc/img/diabook.png b/doc/assets/img/diabook.png similarity index 100% rename from doc/img/diabook.png rename to doc/assets/img/diabook.png diff --git a/doc/img/editor_frio.png b/doc/assets/img/editor_frio.png similarity index 100% rename from doc/img/editor_frio.png rename to doc/assets/img/editor_frio.png diff --git a/doc/img/editor_vier.png b/doc/assets/img/editor_vier.png similarity index 100% rename from doc/img/editor_vier.png rename to doc/assets/img/editor_vier.png diff --git a/doc/img/friendica_rich_editor.png b/doc/assets/img/friendica_rich_editor.png similarity index 100% rename from doc/img/friendica_rich_editor.png rename to doc/assets/img/friendica_rich_editor.png diff --git a/doc/img/frio_location.png b/doc/assets/img/frio_location.png similarity index 100% rename from doc/img/frio_location.png rename to doc/assets/img/frio_location.png diff --git a/doc/img/globe.png b/doc/assets/img/globe.png similarity index 100% rename from doc/img/globe.png rename to doc/assets/img/globe.png diff --git a/doc/img/lock.png b/doc/assets/img/lock.png similarity index 100% rename from doc/img/lock.png rename to doc/assets/img/lock.png diff --git a/doc/img/mic.png b/doc/assets/img/mic.png similarity index 100% rename from doc/img/mic.png rename to doc/assets/img/mic.png diff --git a/doc/img/padlock.png b/doc/assets/img/padlock.png similarity index 100% rename from doc/img/padlock.png rename to doc/assets/img/padlock.png diff --git a/doc/img/paper_clip.png b/doc/assets/img/paper_clip.png similarity index 100% rename from doc/img/paper_clip.png rename to doc/assets/img/paper_clip.png diff --git a/doc/img/post_categorize.png b/doc/assets/img/post_categorize.png similarity index 100% rename from doc/img/post_categorize.png rename to doc/assets/img/post_categorize.png diff --git a/doc/img/post_choose.png b/doc/assets/img/post_choose.png similarity index 100% rename from doc/img/post_choose.png rename to doc/assets/img/post_choose.png diff --git a/doc/img/post_delete.png b/doc/assets/img/post_delete.png similarity index 100% rename from doc/img/post_delete.png rename to doc/assets/img/post_delete.png diff --git a/doc/img/post_link.png b/doc/assets/img/post_link.png similarity index 100% rename from doc/img/post_link.png rename to doc/assets/img/post_link.png diff --git a/doc/img/post_mark.png b/doc/assets/img/post_mark.png similarity index 100% rename from doc/img/post_mark.png rename to doc/assets/img/post_mark.png diff --git a/doc/img/post_share.png b/doc/assets/img/post_share.png similarity index 100% rename from doc/img/post_share.png rename to doc/assets/img/post_share.png diff --git a/doc/img/post_tag.png b/doc/assets/img/post_tag.png similarity index 100% rename from doc/img/post_tag.png rename to doc/assets/img/post_tag.png diff --git a/doc/img/post_thumbs_down.png b/doc/assets/img/post_thumbs_down.png similarity index 100% rename from doc/img/post_thumbs_down.png rename to doc/assets/img/post_thumbs_down.png diff --git a/doc/img/post_thumbs_up.png b/doc/assets/img/post_thumbs_up.png similarity index 100% rename from doc/img/post_thumbs_up.png rename to doc/assets/img/post_thumbs_up.png diff --git a/doc/img/posts_define.png b/doc/assets/img/posts_define.png similarity index 100% rename from doc/img/posts_define.png rename to doc/assets/img/posts_define.png diff --git a/doc/img/video.png b/doc/assets/img/video.png similarity index 100% rename from doc/img/video.png rename to doc/assets/img/video.png diff --git a/doc/img/vier_icons.png b/doc/assets/img/vier_icons.png similarity index 100% rename from doc/img/vier_icons.png rename to doc/assets/img/vier_icons.png diff --git a/doc/autoloader.md b/doc/autoloader.md index 0f15119f7b..7ecb15b6c3 100644 --- a/doc/autoloader.md +++ b/doc/autoloader.md @@ -1,5 +1,4 @@ -Autoloader with Composer -========== +# Autoloader with Composer * [Home](help) * [Developer Intro](help/developers-intro) @@ -10,7 +9,7 @@ It's a command-line tool that downloads required libraries into the `vendor` fol * [Using Composer](help/composer) -## A quick introduction to class autoloading +## A quick introduction to class auto-loading The autoloader dynamically includes the file defining a class when it is first referenced, either by instantiating an object or simply making sure that it is available, without the need to explicitly use "require_once". @@ -87,7 +86,7 @@ class ItemsManager extends BaseManager { ``` Even though we didn't explicitly include the `src/BaseManager.php` file, the autoloader will when this class is first defined, because it is referenced as a parent class. -It works with the "BaseManager" example here and it works when we need to call static methods: +It works with the "BaseManager" example here, and it works when we need to call static methods: ```php // src/Dfrn.php @@ -153,7 +152,7 @@ class Diaspora { } ``` -if you use that class in many places of the code and you don't want to write the full path to the class every time, you can use the "use" PHP keyword +if you use that class in many places of the code, and you don't want to write the full path to the class every time, you can use the "use" PHP keyword ```php // src/Diaspora.php diff --git a/doc/bbcode.md b/doc/bbcode.md index 674a1b9d2a..629fc86a7e 100644 --- a/doc/bbcode.md +++ b/doc/bbcode.md @@ -1,5 +1,4 @@ -Friendica BBCode tags reference -======================== +# Friendica BBCode tags reference * [Creating posts](help/text-editor) @@ -61,8 +60,8 @@ table.bbcodes > * > tr > th { red - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica [img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.png[/img] @@ -103,23 +102,23 @@ table.bbcodes > * > tr > th { Result - [url]http://friendi.ca[/url] - http://friendi.ca + [url]https://friendi.ca[/url] + https://friendi.ca - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica - [bookmark]http://friendi.ca[/bookmark]

        -#^[url]http://friendi.ca[/url] -

        Friendica: http://friendi.ca

        + [bookmark]https://friendi.ca[/bookmark]

        +#^[url]https://friendi.ca[/url] +

        Friendica: https://friendi.ca

        - [bookmark=http://friendi.ca]Bookmark[/bookmark]

        -#^[url=http://friendi.ca]Bookmark[/url]

        -#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Bookmark[/url] -

        Friendica: Bookmark

        + [bookmark=https://friendi.ca]Bookmark[/bookmark]

        +#^[url=https://friendi.ca]Bookmark[/url]

        +#[url=https://friendi.ca]^[/url][url=https://friendi.ca]Bookmark[/url] +

        Friendica: Bookmark

        [url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora post with GUID[/url] @@ -170,7 +169,7 @@ code [code=php]function text_highlight($s,$lang)[/code]1 -
        1.  function text_highlight($s,$lang)
        +
        1. function text_highlight($s,$lang)
        [quote]quote[/quote] @@ -275,21 +274,21 @@ code [table]
        -  [tr]
        -    [th]Header 1[/th]
        -    [th]Header 2[/th]
        -    [th]Header 2[/th]
        -  [/tr]
        -  [tr]
        -    [td]Cell 1[/td]
        -    [td]Cell 2[/td]
        -    [td]Cell 3[/td]
        -  [/tr]
        -  [tr]
        -    [td]Cell 4[/td]
        -    [td]Cell 5[/td]
        -    [td]Cell 6[/td]
        -  [/tr]
        + [tr]
        + [th]Header 1[/th]
        + [th]Header 2[/th]
        + [th]Header 2[/th]
        + [/tr]
        + [tr]
        + [td]Cell 1[/td]
        + [td]Cell 2[/td]
        + [td]Cell 3[/td]
        + [/tr]
        + [tr]
        + [td]Cell 4[/td]
        + [td]Cell 5[/td]
        + [td]Cell 6[/td]
        + [/tr]
        [/table] @@ -372,12 +371,12 @@ code +For other networks (e.g. when you are using the "StatusNet" connector that is used to post to your GNU Social account) the general abstract element will be used.
        [ul]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/ul]
        [list]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -388,12 +387,12 @@ code
        [ol]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/ol]
        [list=1]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -404,8 +403,8 @@ code
        [list=]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -416,8 +415,8 @@ code
        [list=i]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -428,8 +427,8 @@ code
        [list=I]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -440,8 +439,8 @@ code
        [list=a]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -452,8 +451,8 @@ code
        [list=A]
        -  [li] First list element
        -  [li] Second list element
        + [li] First list element
        + [li] Second list element
        [/list]
          @@ -548,7 +547,7 @@ pictures?[/abstract]
          that I wanted to share with you.[/abstract]
          Today I was in the woods and took some real cool pictures ...
        For Twitter and App.net the system will use the defined abstracts.
        -For other networks (e.g. when you are using the "statusnet" connector that is used to post to your GNU Social account) the general abstract element will be used.
        @@ -574,7 +573,7 @@ While taking pictures in the woods I had a really strange encounter... -The [abstract] element is not working with connectors where we post HTML directly, like Tumblr, Wordpress or Pump.io. +The [abstract] element is not working with connectors where we post HTML directly, like Tumblr, WordPress or Pump.io. For the native connections--that is to e.g. Friendica, Hubzilla, Diaspora or GNU Social--the full posting is used and the contacts instance will display the posting as desired. For postings that are delivered via ActivityPub, the text from the abstract is placed in the summary field. @@ -611,10 +610,10 @@ On Mastodon this field is used for the content warning. Additionally, [pre] blocks preserve spaces:
          -
        • [pre]      Spaces[/pre]
        • +
        • [pre] Spaces[/pre]
        -       Spaces + Spaces [nosmile] is used to disable smilies on a post by post basis
        diff --git a/doc/bugs-and-issues.md b/doc/bugs-and-issues.md index 126f6af58e..53d757a43c 100644 --- a/doc/bugs-and-issues.md +++ b/doc/bugs-and-issues.md @@ -1,5 +1,4 @@ -Bugs and Issues -=============== +# Bugs and Issues * [Home](help) @@ -7,7 +6,7 @@ If your server has a support page, you should report any bugs/issues you encount Reporting to your support page before reporting to the developers makes their job easier, as they don't have to deal with bug reports that might not have anything to do with them. Reducing the workload in this way helps us get new features faster. You can also contact the [friendica support group](https://forum.friendi.ca/profile/helpers) and report your problem there. -Bugs are rarely limited to one person, and the chances are somebody from another node has encountered the problem too, and will be able to help you. +Bugs are rarely limited to one person, and the chances are somebody from another node has encountered the issue too, and will be able to help you. If you're a technical user, or your site doesn't have a support page, you'll need to use the [Bug Tracker](https://github.com/friendica/friendica/issues). This is also used for issues with addons. diff --git a/doc/channels.md b/doc/channels.md index 63d2582170..448118082e 100644 --- a/doc/channels.md +++ b/doc/channels.md @@ -1,5 +1,4 @@ -Channels -===== +# Channels * [Home](help) @@ -18,8 +17,7 @@ On the contact page you can define the channel frequency for every contact. The * Display only few posts: When a contact creates a lot of posts in a short period, this setting reduces the number of displayed posts in every channel. * Never display posts: Posts from this contact will never be displayed in any channel. -Predefined Channels ---- +## Predefined Channels * For you: Posts from contacts you interact with and who interact with you. In detail, it consists of: * Posts from people you interact with on a more than average level. @@ -38,8 +36,7 @@ Predefined Channels * Audio: Posts with audio. * Videos: Posts with videos. -User defined Channels ---- +## User defined Channels In the "Channels" settings you can create your own channels. @@ -54,8 +51,7 @@ Each channel is defined by these values: * Full Text Search: This can be used to include or exclude content, based on the content and some additional keywords. It uses the "boolean mode" operators from MariaDB: https://mariadb.com/kb/en/full-text-index-overview/#in-boolean-mode * Images, Videos, Audio: When selected, you will see content with the selected media type. This can be combined. If none of these fields are checked, you will see any content, with or without attached media. -Additional keywords for the full text search ---- +## Additional keywords for the full text search Additionally to the search for content, there are keywords that can be used in the full text search. Alternatives are presented with "|". diff --git a/doc/chats.md b/doc/chats.md index 1fd76ec6f7..ea50719430 100644 --- a/doc/chats.md +++ b/doc/chats.md @@ -1,5 +1,4 @@ -Chats -===== +# Chats * [Home](help) @@ -8,10 +7,9 @@ There are two possibilities to use chat on your friendica site * IRC Chat * Jappix -IRC-Chat Addon ---- +## IRC-Chat Addon -After activating the addon, you can find the chat at [yoursite.com/irc](../irc). +After activating the addon, you can find the chat at `https://your-site.info/irc`. Note: you can use this chat without any login at your site so that everyone could use it. If you follow the link, you will see the login page of the IRC chat. @@ -25,8 +23,8 @@ The first line shows your name and your current IP address. The right part of the window shows all users. The lower part of the window contains an input field. -Jappix Mini ---- +## Jappix Mini + The Jappix Mini Addon creates a chatbox for jabber- and XMPP-contacts. You should already have a jabber/XMPP-account before setting up the addon. @@ -39,9 +37,11 @@ You can use several servers to create an account: ### 1. Basics -At first you have to get the current version. You can either pull it from [GitHub](https://github.com) like so: - - $> cd /var/www/virtual/YOURSPACE/html/addon; git pull +First you have to get the current version. You can either pull it from [GitHub](https://github.com) like so: +```sh +cd /var/www/virtual/YOURSPACE/html/addon +git pull +``` Or you can download a tar archive here: [jappixmini.tgz](https://github.com/friendica/friendica-addons/blob/stable/jappixmini.tgz) (click at „view raw“). @@ -59,13 +59,13 @@ Activate the BOSH proxy. Go to your user account settings next and choose the addon page. Scroll down until you find the Jappix Mini addon settings. -At first you have to activate the addon. +First you have to activate the addon. Now add your Jabber/XMPP name, the domain/server (without "http"; just "jappix.com"). For „Jabber BOSH Host“ you could use "https://bind.jappix.com/". Note that you need another BOSH server if you do not use jappix.com for your XMPP account. -You can find further information in the „Configuration Help“-section below this fields. -At last you have enter your password (there are some more optional options, you can choose). +You can find further information in the „Configuration Help“-section below these fields. +Finally you enter your password (there are some more optional options, you can choose). Finish these steps with "send" to save the entries. Now, you should find the chatbox at the lower right corner of your browser window. diff --git a/doc/circles-and-privacy.md b/doc/circles-and-privacy.md index abec72f15a..a1324def79 100644 --- a/doc/circles-and-privacy.md +++ b/doc/circles-and-privacy.md @@ -1,13 +1,11 @@ -Circles and Privacy -================== +# Circles and Privacy * [Home](help) - Circles are merely collections of friends. But Friendica uses these to unlock some very powerful features. -**Setting Up Circles** +## Setting Up Circles To create a circle, visit your Friendica "Contacts" page and select "Create a new circle". Give the circle a name. @@ -21,7 +19,7 @@ Below that is another box containing all of your friends who are *not* members o If you click on a photo of a person who isn't in the circle, they will be put into the circle. If you click on a photo of a person who is in the circle, they will be removed from it. -**Access Control** +## Access Control Once you have created a circle, you may use it in any access control list. This is the little lock icon beneath the status update box on your home page. @@ -40,7 +38,7 @@ You will see that since you are only viewing a certain circle of people, your st This is how you keep your future employers from seeing what you write to your drinking buddies. You can override this setting, but this makes it easy to separate your conversations into different friend circles. -**Default Post Privacy** +## Default Post Privacy By default, Friendica assumes that you want all of your posts to be private. Therefore, when you sign up, Friendica creates a circle for you that it will automatically add all of your contacts to. @@ -51,7 +49,7 @@ Note that this behaviour can be overridden by your site admin, in which case you If you want your posts to be "public" by default, you can change your default post permissions on your Settings page. You also have the option to change which circles you post to by default or which circle your new contacts get placed into by default. -**Privacy Concerns To Be Aware Of** +## Privacy Concerns To Be Aware Of These private conversations work best when your friends are Friendica members. We know who else can see the conversations - nobody, *unless* your friends cut and paste the messages and send them to others. @@ -66,20 +64,18 @@ If you look at the Contact Edit page for any person, we will tell you whether or Once you have created a post, you can not change the permissions assigned. Within seconds it has been delivered to lots of people - and perhaps everybody it was addressed to. If you mistakenly created a message and wish to take it back, the best you can do is delete it. -We will send out a delete notification to everybody who received the message - and this should wipe out the message with the same speed as it was initially propagated. +We will send out a deleted notification to everybody who received the message - and this should wipe out the message with the same speed as it was initially propagated. In most cases, it will be completely wiped from the Internet - in under a minute. Again, this applies to Friendica networks. Once a message spreads to other networks, it may not be removed quickly, and in some cases, it may not be removed at all. - -Profiles, Photos, and Privacy -============================= +# Profiles, Photos, and Privacy The decentralised nature of Friendica (many websites exchanging information rather than one website which controls everything) has some implications with privacy as it relates to people on other sites. There are things you should be aware of, so you can decide best how to interact privately. -**Photos** +## Photos Sharing photos privately is a problem. We can only share them __privately__ with Friendica members. @@ -90,7 +86,7 @@ Your friends on other networks will be blocked from viewing these private photos Our developers are working on solutions to allow access to your friends - no matter what network they are on. However we take privacy seriously and don't behave like some networks that __pretend__ your photos are private, but make them available to others without proof of identity. -**Profiles** +## Profiles Your profile and "wall" may also be visited by your friends from other networks, and you can block access to these by web visitors that Friendica doesn't know. Be aware that this could include some of your friends on other networks. diff --git a/doc/composer.md b/doc/composer.md index d68acba1c3..89bc8fb2d0 100644 --- a/doc/composer.md +++ b/doc/composer.md @@ -1,5 +1,4 @@ -Using Composer -============== +# Using Composer * [Home](help) * [Developer Intro](help/developers-intro) @@ -56,7 +55,7 @@ If you don't need to use any third-party library, then you don't need to use Com #### Adding a third-party library to Friendica Does your shiny new [Addon](help/addons) need to rely on a third-party library not required by Friendica yet? -First of all, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. +First, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. This file is the configuration of Friendica for Composer. It lists details about the Friendica project, but also a list of required dependencies and their target version. Here's a simplified version of the one we currently use on Friendica: diff --git a/doc/config.md b/doc/config.md index afd4e65277..b9a732473a 100644 --- a/doc/config.md +++ b/doc/config.md @@ -1,5 +1,4 @@ -Config values that can only be set in config/local.config.php -========================================================== +# Config values that can only be set in config/local.config.php * [Home](help) diff --git a/doc/connectors.md b/doc/connectors.md index 77d44e909f..df27cc5e6b 100644 --- a/doc/connectors.md +++ b/doc/connectors.md @@ -1,5 +1,4 @@ -Connectors -========== +# Connectors * [Home](help) @@ -8,35 +7,30 @@ They are only required for posting to existing accounts on for example Bluesky, For Bluesky and Tumblr you can also enable a bidirectional synchronisation, so that you can use Friendica to read your timeline from Tumblr or Bluesky. There is also a connector for accessing your email INBOX. -Instructions For Connecting To People On Specific Services -========================================================== +# Instructions For Connecting To People On Specific Services -Friendica ---- +## Friendica You can either connect to others by providing your Identity Address on the 'Connect' page of any Friendica member. -Or you can put their Identity Address into the Connect box on your [Contacts](contacts) page. +Or you can put their Identity Address into the Connect box on your [Contacts](contact) page. -Diaspora ---- +## Diaspora -Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contacts) page. +Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contact) page. -Blogger, Wordpress, RSS feeds, arbitrary web pages ---- +## Blogger, WordPress, RSS feeds, arbitrary web pages -Put the URL into the Connect box on your [Contacts](contacts) page. -PLease note that you will not be able to reply to these contacts. +Put the URL into the Connect box on your [Contacts](contact) page. +PLease note that you will not be able to reply to these contacts. This feed reader feature will allow you to _connect_ with millions of pages on the internet. -All that the pages need to have is a discoverable feed using either the RSS or Atom syndication format, and which provides an author name and a site image in a form which we can extract. +All that the pages need to have is a discoverable feed using either the RSS or Atom syndication format, and which provides an author name and a site image in a form which we can extract. -Email ---- +## Email If the php module for IMAP support is available on your server, Friendica can connect to email contacts as well. Configure the email connector from your [Settings](settings) page. -Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contacts) page. +Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contact) page. They must be the sender of a message which is currently in your INBOX for the connection to succeed. You may include email contacts in private conversations. diff --git a/doc/de/account-basics.md b/doc/de/account-basics.md index ce66818359..2e309416fc 100644 --- a/doc/de/account-basics.md +++ b/doc/de/account-basics.md @@ -1,9 +1,7 @@ -Account - Basics -============== +# Account - Basics * [Zur Startseite der Hilfe](help) - ## Registrierung Viele, aber nicht alle Friendica-Knoten (Server) bieten die Möglichkeit zur Registrierung an. @@ -19,15 +17,12 @@ Falls du keine [OpenID-Adresse](https://de.wikipedia.org/wiki/OpenID">OpenID-Adr Solltest du eine OpenID Adresse haben, kannst Du sie im ersten Feld eintragen und "Registrieren" klicken. Friendica wird versuchen, so viele Informationen wie möglich von Deinem OpenID-Provider zu übernehmen, um diese in Dein Profil auf dieser Seite einzutragen. - ### Dein vollständiger Name Bitte trage bei "vollständiger Name" Deinen **gewünschten Namen** ein, wie er über deinen Beiträgen angezeigt werden soll. -Du kannst deinen echten Namen eintragen, kannst Dir aber auch einen Namen ausdenken. Einen Zwang zu dem sogenannten Klarnamen gibt es nicht. +Du kannst deinen echten Namen eintragen, kannst dir aber auch einen Namen ausdenken. Einen Zwang zu dem sogenannten Klarnamen gibt es nicht. - - -### Email-Adresse +### E-Mail-Adresse Bitte trage eine richtige Email-Adresse ein. Dies ist die einzige persönliche Information, die korrekt sein muss. @@ -51,23 +46,21 @@ Durch die Art, wie der Spitzname genutzt wird, gibt es bestimmte Einschränkunge Dieser Spitzname wird an vielen Stellen genutzt, um Deinen Account zu identifizieren, daher ist es nicht möglich ihn später zu ändern. - ### Verzeichnis-Eintrag Das Registrierungsformular erlaubt es dir, direkt auszuwählen, ob Du im [Onlineverzeichnis](https://dir.friendica.social/) (Friendica Directory) aufgelistet wirst oder nicht. -Das ist wie ein Telefonbuch und Du entscheidest, ob du darin eingetragen werden möchtest, oder nicht. +Das ist wie ein Telefonbuch und du entscheidest, ob du darin eingetragen werden möchtest, oder nicht. -* Wir bitten dich, "Ja" zu wählen, damit Andere Dich finden können, so wie Du sie finden kannst +* Wir bitten dich, "Ja" zu wählen, damit Andere dich finden können, so wie Du sie finden kannst * Wählst Du "Nein", bist Du für Andere *nicht einfach auffindbar* Was auch immer Du wählst, kann jederzeit nach dem Login in Deinen Account-Einstellungen geändert werden. - ### Registrierung Sobald Du die nötigen Informationen eingegeben hast, klicke auf "Registrieren". Eine Email mit den Registrierungsdetails und Deinem Initialpasswort wird an die hinterlegte Email-Adresse geschickt. -Bitte prüfe den Posteingang (inkl. dem Spam-Ordner). +Bitte prüfe den Posteingang (inklusive dem Spam-Ordner). ## Login-Seite @@ -78,7 +71,7 @@ Du kannst entweder Deinen Spitznamen oder die Email-Adresse als Login-Namen nutz Wenn Du Deinen Account nutzt, um unterschiedliche '[Seiten](help/pages)' zu verwalten, die die gleiche Email-Adresse verwenden, dann nutze bitte den Spitznamen des Accounts, der verwaltet werden soll. *Wenn* Dein Account OpenID nutzt, dann kannst Du Deine OpenID-Adresse als Login-Name nutzen und das Passwort-Feld frei lassen. -Du wirst zu Deinem OpenID-Anbieter weitergeleitet, wo Du Deine Anmeldung abschließt. +Du wirst zu deinem OpenID-Anbieter weitergeleitet, wo Du Deine Anmeldung abschließt. Wenn Du OpenID nicht nutzt, dann gib Dein Passwort ein, das Du mit der Registrierungsmail erhalten hast. Das Passwort muss genau so geschrieben werden, wie es in der Email steht; Groß- und Kleinschreibung wird beachtet. diff --git a/doc/de/addons.md b/doc/de/addons.md index 5f42a53c2a..78fccd09d3 100644 --- a/doc/de/addons.md +++ b/doc/de/addons.md @@ -1,5 +1,4 @@ -Friendica Addon/Entwicklung -============== +# Friendica Addon/Entwicklung * [Zur Startseite der Hilfe](help) @@ -28,15 +27,14 @@ Registriere deine Addon-Hooks während der Installation. \Friendica\Core\Hook::register($hookname, $file, $function); -$hookname ist ein String und entspricht einem bekannten Friendica-Hook. +`$hookname` ist ein String und entspricht einem bekannten Friendica-Hook. -$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt. -Das *sollte* "addon/addon_name/addon_name.php' sein. +$file steht für den Pfadnamen, der relativ zum Top-Level-Friendica-Verzeichnis liegt. +Das *sollte* `addon/addon_name/addon_name.php` sein. $function ist ein String und der Name der Funktion, die ausgeführt wird, wenn der Hook aufgerufen wird. -Argumente ---- +## Argumente Deine Hook-Callback-Funktion wird mit höchstens einem Argumenten aufgerufen @@ -51,8 +49,7 @@ Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst. -Module ---- +## Module Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. Um ein Addon als Modul zu nutzen, ist es nötig, die Funktion "addon_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. @@ -72,8 +69,7 @@ Sie können auch `addon_name_post()` umfassen, welches vor der content-Funktion Du kannst ebenso `addon_name_init()` nutzen, was oft frühzeitig aufgerufen wird und das Modul initialisert. -Derzeitige Hooks ---- +## Derzeitige Hooks **'authenticate'** - wird aufgerufen, wenn sich der User einloggt. $b ist ein Array @@ -189,8 +185,7 @@ Dieser Hook kann dafür verwendet werden, alternative Erkennungsfunktionen einzu - wird aufgerufen nachdem in include/nav,php der Inhalt des Navigations Menüs erzeugt wurde. - $b ist ein Array, das $nav wiederspiegelt. -Komplette Liste der Hook-Callbacks ---- +## Komplette Liste der Hook-Callbacks Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Apr-2018 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind. diff --git a/doc/de/bbcode.md b/doc/de/bbcode.md index 2057d40c55..2b58f52a7b 100644 --- a/doc/de/bbcode.md +++ b/doc/de/bbcode.md @@ -1,5 +1,4 @@ -Referenz der Friendica BBCode Tags -======================== +# Referenz der Friendica BBCode Tags * [Zur Startseite der Hilfe](help) @@ -61,8 +60,8 @@ table.bbcodes > * > tr > th { rot - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica [img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.png[/img] @@ -103,23 +102,23 @@ table.bbcodes > * > tr > th { Ergebnis - [url]http://friendi.ca[/url] - http://friendi.ca + [url]https://friendi.ca[/url] + https://friendi.ca - [url=http://friendi.ca.com]Friendica[/url] - Friendica + [url=https://friendi.ca.com]Friendica[/url] + Friendica - [bookmark]http://friendi.ca[/bookmark]

        -#^[url]http://friendi.ca[/url] -

        Friendica: http://friendi.ca

        + [bookmark]https://friendi.ca[/bookmark]

        +#^[url]https://friendi.ca[/url] +

        Friendica: https://friendi.ca

        - [bookmark=http://friendi.ca]Lesezeichen[/bookmark]

        -#^[url=http://friendi.ca]Lesezeichen[/url]

        -#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Lesezeichen[/url] -

        Friendica: Lesezeichen

        + [bookmark=https://friendi.ca]Lesezeichen[/bookmark]

        +#^[url=https://friendi.ca]Lesezeichen[/url]

        +#[url=https://friendi.ca]^[/url][url=https://friendi.ca]Lesezeichen[/url] +

        Friendica: Lesezeichen

        [url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora Beitrag mit GUID[/url] @@ -171,7 +170,7 @@ Zeilen [code=php]function text_highlight($s,$lang)[/code] -
        1.  function text_highlight($s,$lang)
        +
        1. function text_highlight($s,$lang)
        [quote]Zitat[/quote] @@ -255,21 +254,21 @@ Zeilen [table]
        -  [tr]
        -    [th]Kopfzeile 1[/th]
        -    [th]Kopfzeile 2[/th]
        -    [th]Kopfzeile 2[/th]
        -  [/tr]
        -  [tr]
        -    [td]Zelle 1[/td]
        -    [td]Zelle 2[/td]
        -    [td]Zelle 3[/td]
        -  [/tr]
        -  [tr]
        -    [td]Zelle 4[/td]
        -    [td]Zelle 5[/td]
        -    [td]Zelle 6[/td]
        -  [/tr]
        + [tr]
        + [th]Kopfzeile 1[/th]
        + [th]Kopfzeile 2[/th]
        + [th]Kopfzeile 2[/th]
        + [/tr]
        + [tr]
        + [td]Zelle 1[/td]
        + [td]Zelle 2[/td]
        + [td]Zelle 3[/td]
        + [/tr]
        + [tr]
        + [td]Zelle 4[/td]
        + [td]Zelle 5[/td]
        + [td]Zelle 6[/td]
        + [/tr]
        [/table] @@ -352,12 +351,12 @@ Zeilen
        [ul]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/ul]
        [list]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -368,12 +367,12 @@ Zeilen
        [ol]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/ol]
        [list=1]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -384,8 +383,8 @@ Zeilen
        [list=]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -396,8 +395,8 @@ Zeilen
        [list=i]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -408,8 +407,8 @@ Zeilen
        [list=I]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -420,8 +419,8 @@ Zeilen
        [list=a]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -432,8 +431,8 @@ Zeilen
        [list=A]
        -  [li] Erstes Listenelement
        -  [li] Zweites Listenelement
        + [li] Erstes Listenelement
        + [li] Zweites Listenelement
        [/list]
          @@ -551,7 +550,7 @@ Als ich die Bilder im Wald aufgenommen habe, hatte ich eine wirklich ungewö
        -Für Verbindungen zu Netzwerken, zu denen Friendica den HTML Code postet, wie Tumblr, Wordpress oder Pump.io wird das [abstract] Element nicht verwendet. +Für Verbindungen zu Netzwerken, zu denen Friendica den HTML Code postet, wie Tumblr, WordPress oder Pump.io wird das [abstract] Element nicht verwendet. Bei nativen Verbindungen; das heißt zu z.B. Friendica, Hubzilla, Diaspora oder GNU Social Kontakten; wird der ungekürzte Beitrag übertragen. Die Instanz des Kontakts kümmert sich um die Darstellung. @@ -595,4 +594,3 @@ Du kannst alle [style=text-shadow: 0 0 4px #CC0000;]CSS-Eigenschaften[/style] di Du kannst alle CSS-Eigenschaften dieses Inline-Textes ändern- - diff --git a/doc/de/bugs-and-issues.md b/doc/de/bugs-and-issues.md index 4db1bd6aa3..74c7579667 100644 --- a/doc/de/bugs-and-issues.md +++ b/doc/de/bugs-and-issues.md @@ -1,16 +1,15 @@ -Bugs und Probleme -=============== +# Bugs und Probleme * [Zur Startseite der Hilfe](help) -Du solltest jeden Bug und jedes Problem, den/das Du findest, zunächst dem Administrator (oder gegebenenfalls der Support-Seite) Deines Servers melden, statt auf der allgemeinen Bug-Seite. +Du solltest jeden Bug und jedes Problem, den/das Du findest, zunächst dem Administrator (oder gegebenenfalls der Support-Seite) Deines Servers melden, statt auf der allgemeinen Bug-Seite. Das erleichtert den Entwicklern ihre Arbeit (z. B. neue Features zu entwickeln), da sie sich nicht mit Fehlern beschäftigen müssen, mit denen sie nichts zu tun haben. -Wenn Du technisch versiert bist oder Dein Knoten keine Support-Seite hat, dann kannst Du den Bug Tracker nutzen. -Bitte durchsuche zunächst die Seite, ob es bereits einen offenen Bug gibt, der Deiner Anfrage entspricht. +Wenn Du technisch versiert bist oder Dein Knoten keine Support-Seite hat, dann kannst Du den Bug Tracker nutzen. +Bitte durchsuche zunächst die Seite, ob es bereits einen offenen Bug gibt, der Deiner Anfrage entspricht. -Liefere so viele Informationen wie möglich zu dem Bug. -Hierzu gehört auch die **komplette** Fehlermeldung oder Notiz und alle Schritte, die zu dem Fehler geführt haben. -Es ist generell besser, zu viele Informationen zu liefern, als zu wenige. +Liefere so viele Informationen wie möglich zu dem Bug. +Hierzu gehört auch die **komplette** Fehlermeldung oder Notiz und alle Schritte, die zu dem Fehler geführt haben. +Es ist generell besser, zu viele Informationen zu liefern, als zu wenige. Lies Dir diesen Artikel (mehrsprachig) durch, um mehr über **gute** Bug-Reports zu erfahren. diff --git a/doc/de/channels.md b/doc/de/channels.md index 686fd129b1..7085065d60 100644 --- a/doc/de/channels.md +++ b/doc/de/channels.md @@ -1,5 +1,4 @@ -Kanäle (Channels) -===== +# Kanäle (Channels) * [Home](help) @@ -18,8 +17,7 @@ Auf der Profilseite kannst du die Kanal-Frequenz für jeden Kontakt definieren. * Zeige nur einige Beiträge an: Wenn ein Kontakt viele Beiträge in einem kurzen Zeitraum erstellt, reduziert diese Einstellung die Anzahl der angezeigten Beiträge in jedem Kanal. * Zeige keine Beiträge an: Beiträge von diesem Kontakt werden in keinem Kanal angezeigt. -Voreingestellte Kanäle ---- +## Voreingestellte Kanäle * Für Dich: Beiträge von Kontakten mit denen du interagierst und die mit dir interagieren. Im Detail bestehend aus: * Beiträge von Leuten, mit denen du überdurchschnittlich viel interagierst. @@ -38,8 +36,7 @@ Voreingestellte Kanäle * Audio: Beiträge mit Audio. * Videos: Beiträge mit Videos. -Vom Benutzer eingestellte Kanäle ---- +## Vom Benutzer eingestellte Kanäle In den Einstellungen, unter "Kanäle", kannst du deine eigenen Kanäle erstellen. @@ -54,8 +51,7 @@ Jeder Kanal wird durch diese Werte definiert: * Volltextsuche: Dies kann genutzt werden um Inhalte, basierend auf dem Inhalt und ein paar zusätzlichen Schlüsselwörtern, ein- oder auszuschließen. Es nutzt die "boolean mode"-Operatoren von MariaDB: https://mariadb.com/kb/en/full-text-index-overview/#in-boolean-mode * Bilder, Videos, Audio: Wenn ausgewählt, wirst du Inhalte mit dem gewählten Medientyp sehen. Diese Optionen können kombiniert werden. Wenn keines dieser Felder ausgewählt wurde, wirst du alle Inhalte, mit oder ohne angefügten Medien, sehen. -Zusätzliche Schlüsselwörter für die Volltextsuche ---- +## Zusätzliche Schlüsselwörter für die Volltextsuche Zusätzlich zu der Suche nach Inhalten, gibt es Schlüsselwörter, die in der Volltextsuche genutzt werden können. Alternativen werden durch "|" dargestellt. diff --git a/doc/de/chats.md b/doc/de/chats.md index 83c55e991c..b5a57a6f89 100644 --- a/doc/de/chats.md +++ b/doc/de/chats.md @@ -1,5 +1,4 @@ -Chats -===== +# Chats * [Zur Startseite der Hilfe](help) diff --git a/doc/de/circles-and-privacy.md b/doc/de/circles-and-privacy.md index dcb5f3259f..bd50e825de 100644 --- a/doc/de/circles-and-privacy.md +++ b/doc/de/circles-and-privacy.md @@ -1,5 +1,4 @@ -Circles und Privatsphäre -================== +# Circles und Privatsphäre * [Zur Startseite der Hilfe](help) @@ -45,9 +44,9 @@ Standardmäßig geht Friendica davon aus, dass alle deine Beiträge privat sein Aus diesem Grund erstellt Friendica nach der Anmeldung eine Circle, in die automatisch alle deine Kontakte hinzugefügt werden. Alle deine Beiträge sind nur auf diese Circle beschränkt. -Beachte, dass diese Einstellung von deinem Seiten-Administrator überschrieben werden kann, was bedeutet, dass alle deine Beiträge standardmäßig "öffentlich" sind (bspw. für das gesamte Internet). +Beachte, dass diese Einstellung von deinem Seiten-Administrator überschrieben werden kann, was bedeutet, dass alle deine Beiträge standardmäßig "öffentlich" sind (beispielweise für das gesamte Internet). -Wenn du deine Beiträge standardmäßig "öffentlich" haben willst, dann kannst du deine Standardzugriffsrechte auf deiner Einstellungseite ändern. +Wenn du deine Beiträge standardmäßig "öffentlich" haben willst, dann kannst du deine Standardzugriffsrechte auf deiner Einstellungsseite ändern. Dort kannst du außerdem festlegen, welchen Circles standardmäßig deine Beiträge erhalten oder in welche Circle deine neuen Kontakte standardmäßig eingeordnet werden. **Fragen der Privatssphäre, die zu beachten sind** @@ -64,19 +63,18 @@ Du musst **sehr** vorsichtig sein, wenn du Mitglieder anderer Netzwerke in einer Wenn du auf die "Kontakt bearbeiten"-Seite einer Person gehst, zeigen wir dir, ob sie Mitglied eines unsicheren Netzwerks ist oder nicht. Sobald du einen Post erstellt hast, kannst du die Zugriffsrechte nicht mehr ändern. -Innerhalb von Sekunden ist dieser an viele verschiedene Personen verschickt worden - möglicherweise bereits an alle Addressierten. +Innerhalb von Sekunden ist dieser an viele verschiedene Personen verschickt worden - möglicherweise bereits an alle Adressierten. Wenn du versehentlich eine Nachricht erstellt hast und sie zurücknehmen willst, dann ist es das beste, diese zu löschen. Wir senden eine Löschmitteilung an jeden, der deine Nachricht erhalten hat - und das sollte die Nachricht genauso schnell löschen, wie sie zunächst erstellt wurde. In vielen Fällen wird sie in weniger als einer Minute aus dem Internet gelöscht. Nochmals: das gilt für Friendica-Netzwerke. Sobald eine Nachricht an ein anderes Netzwerk geschickt wurde, kann es nicht mehr so schnell gelöscht werden und in manchen Fällen auch gar nicht mehr. -Wenn du das bisher noch nicht wusstest, dann empfehlen wir dir, deine Freunde dazu zu ermutigen, auch Friendica zu nutzen, da alle diese Privatsphären-Einstellungen innerhalb eines privatsphärenbewussten Netzwerk viel besser funktionieren. +Wenn du das bisher noch nicht wusstest, dann empfehlen wir dir, deine Freunde dazu zu ermutigen, auch Friendica zu nutzen, da alle diese Privatsphären-Einstellungen innerhalb eines privatsphärenbewussten Netzwerks viel besser funktionieren. Viele andere Netzwerke, mit denen sich Friendica verbinden kann, bieten keine Kontrolle über die Privatsphäre. -Profile, Fotos und die Privatsphäre -============================= +# Profile, Fotos und die Privatsphäre Die dezentralisierte Natur von Friendica (statt eine Webseite zu haben, die alles kontrolliert, gibt es viele Webseiten, die Information austauschen) hat in der Kommunikation mit anderen Seiten einige Konsequenzen. Du solltest dir über einige Dinge bewusst sein, um am besten entscheiden zu können, wie du mit deiner Privatsphäre umgehst. @@ -90,7 +88,7 @@ Wir können die Identität von Friendica-Nutzern prüfen, da es hierfür einen M Deine Freunde anderer Netzwerke werden deine privaten Fotos nicht sehen können, da wir deren Identität nicht überprüfen können. Unsere Entwickler arbeiten an einer Lösung, um deinen Freunden den Zugriff zu ermöglichen - unabhängig, zu welchem Netzwerk sie gehören. -Wir nehmen hingegen Privatsphäre ernst und agieren nicht wie andere Netzwerke, die __nur so tun__ als ob deine Fotos privat sind, sie aber trotzdem anderen ohne Identitätsprüfung zeigen. +Wir nehmen hingegen Privatsphäre ernst und agieren nicht wie andere Netzwerke, die __nur so tun__, als ob deine Fotos privat sind, sie aber trotzdem anderen ohne Identitätsprüfung zeigen. **Profile** diff --git a/doc/de/connectors.md b/doc/de/connectors.md index fe2d739fd5..7aaa250563 100644 --- a/doc/de/connectors.md +++ b/doc/de/connectors.md @@ -1,38 +1,35 @@ -Konnektoren (Connectors) -========== +# Konnektoren (Connectors) * [Zur Startseite der Hilfe](help) -Konnektoren erlauben es Dir, Dich mit anderen sozialen Netzwerken zu verbinden. +Konnektoren erlauben es Dir, Dich mit anderen sozialen Netzwerken zu verbinden. Mit diesen Konnektoren kannst Du z.B. zu Bluesky, Tumblr oder Twitter posten. -Für Bluesky und Tumblr gibt es eine bidirektionale Verbindung, d.h. du kannst Friendica nutzen, um deine Timeline von diesen Diensten zu lesen. +Für Bluesky und Tumblr gibt es eine bidirektionale Verbindung, d.h. du kannst Friendica nutzen, um deine Timeline von diesen Diensten zu lesen. Außerdem gibt es einen Konnektor, um Deinen Email-Posteingang zu nutzen. Wenn Du keinen eigenen Knoten betreibst und wissen willst, ob der Server Deiner Wahl diese Konnektoren installiert hat, kannst Du Dich darüber auf der Seite '<domain_des_friendica-servers>/friendica' informieren. -Anleitung, um sich mit Personen in bestimmten Netzwerken zu verbinden -========================================================== +# Anleitung, um sich mit Personen in bestimmten Netzwerken zu verbinden -**Friendica** +## Friendica -Du kannst Dich verbinden, indem Du die Adresse Deiner Identität (<dein_nick>@<dein_friendica-host>) auf der "Verbinden"-Seite des Friendica-Nutzers eingibst. -Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["Kontakt"-Seite](contacts) eingeben. +Du kannst Dich verbinden, indem Du die Adresse Deiner Identität (<dein_nick>@<dein_friendica-host>) auf der "Verbinden"-Seite des Friendica-Nutzers eingibst. +Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["Kontakt"-Seite](contact) eingeben. +## Diaspora -**Diaspora** +Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contact) in das Feld "Neuen Kontakt hinzufügen" ein. -Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. +## Blogger, WordPress, RSS feeds, andere Webseiten -**Blogger, Wordpress, RSS feeds, andere Webseiten** - -Trage die URL auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. +Trage die URL auf Deiner ["Kontakte"-Seite](contact) in das Feld "Neuen Kontakt hinzufügen" ein. Du hast keine Möglichkeit, diesen Kontakten zu antworten. -Das erlaubt Dir, Dich mit Millionen von Seiten im Internet zu _verbinden_. -Alles, was dafür nötig ist, ist dass die Seite einen Feed im RSS- oder Atom Syndication-Format nutzt und welches einen Autoren und ein Bild zur Seite liefert. +Das erlaubt Dir, Dich mit Millionen von Seiten im Internet zu _verbinden_. +Alles, was dafür nötig ist, ist dass die Seite einen Feed im RSS- oder Atom Syndication-Format nutzt und welches einen Autoren und ein Bild zur Seite liefert. -**Email** +## Email -Konfiguriere den Email-Konnektor auf Deiner [Einstellungsseite](settings). -Wenn Du das gemacht hast, kannst Du auf Deiner ["Kontakte"-Seite](contacts) die Email-Adresse in das Feld "Neuen Kontakt hinzufügen" eintragen. -Diese Email-Adresse muss jedoch bereits mit einer Nachricht in Deinem Email-Posteingang auf dem Server liegen. +Konfiguriere den Email-Konnektor auf Deiner [Einstellungsseite](settings). +Wenn Du das gemacht hast, kannst Du auf Deiner ["Kontakte"-Seite](contact) die Email-Adresse in das Feld "Neuen Kontakt hinzufügen" eintragen. +Diese Email-Adresse muss jedoch bereits mit einer Nachricht in Deinem Email-Posteingang auf dem Server liegen. Du hast die Möglichkeit, Email-Kontakte in Deine privaten Unterhaltungen einzubeziehen. diff --git a/doc/de/developers.md b/doc/de/developers.md index 4c5e4a62b9..1623a116c1 100644 --- a/doc/de/developers.md +++ b/doc/de/developers.md @@ -1,5 +1,4 @@ -Friendica - Entwickler-Guide -========== +# Friendica - Entwickler-Guide * [Zur Startseite der Hilfe](help) @@ -9,19 +8,19 @@ Zunächst erstelle Dir per 'git clone https://github.com/friendica/friendica.git Erstelle Deine eigene Kopie (fork) der Ursprungsdaten auf Github, an der Du dann entspannt arbeiten kannst. Deine Arbeiten sollten mit einem neuen Arbeitszweig (branch) beginnen, den du vom develop Zweig des Repositories beginnst. -Die Anleitung unter [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) erklärt Dir genau, wie Du das tun musst. +Die Anleitung unter [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) erklärt dir genau, wie du das tun musst. Gehe dann nach getaner Arbeit zu Deiner Github-Seite und erstelle eine "Pull request", um Deine Änderungen in das Hauptprojekt einzugliedern (merge). -Solltest du keine Idee haben, an welcher Stelle du einsteigen könntest. +Solltest du keine Idee haben, an welcher Stelle du einsteigen könntest? Wir haben einige Aufgaben auf github mit dem Schlagwort *Junior Job* versehen. Bei diesen Aufgaben gehen wir davon aus, dass sie geeignete Einstiegsstellen sind. -Du musst dich aber natürlich nicht mit diesen Aufgaben beschäftigen um den Friendica Code zu verbeesern. +Du musst dich aber natürlich nicht mit diesen Aufgaben beschäftigen um den Friendica Code zu verbessern. **Wichtig** Bitte hole Dir alle Änderungen aus dem Projektverzeichnis und führe sie mit Deiner Arbeit zusammen, **bevor** Du Deine "pull request" erstellst. Wir behalten es uns vor, Patches abzulehnen, die eine große Anzahl an Fehlern hervorrufen. -Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle feinen Unterschiede in konfliktären Versionen erkennen können. +Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle feinen Unterschiede in konfliktähren Versionen erkennen können. Außerdem: **teste Deine Änderungen!** Vergiss nicht, dass eine simple Fehlerlösung einen anderen Fehler auslösen kann. Lass Deine Änderungen von einem erfahrenen Friendica-Entwickler gegenprüfen. diff --git a/doc/de/events.md b/doc/de/events.md index b4979da1da..92a069f848 100644 --- a/doc/de/events.md +++ b/doc/de/events.md @@ -6,7 +6,6 @@ Veranstaltungen sind spezielle Postings. Die Veranstaltungen, die Du und deine Kontakte teilen, können unter [/events](/events) auf deiner Instanz aufgefunden werden. Um da hinzukommen gehe über den Tab "Veranstalltungen", abhänig von dem Theme, das du benutzt, ist der eventuell ein zusätzlicher link im Navigationsmenü der Seite vorhanden. - ## Veranstaltungsübersicht Die Übersichtsseite zeigt den Kalender des aktuellen Monats an, plus einige Tage am Beginn und am Ende. diff --git a/doc/de/export-import-contacts.md b/doc/de/export-import-contacts.md index c4d28c646d..ad83875f00 100644 --- a/doc/de/export-import-contacts.md +++ b/doc/de/export-import-contacts.md @@ -7,7 +7,7 @@ Die exportierte Liste wird als CSV Datei in einem zu anderen Plattformen, z.B. M ## Export der gefolgten Kontakte -Um die Liste der Kontakte *denen du folgst* zu exportieren, geht die [Einstellungen Persönliche Daten exportieren](settings/userexport) und klicke den [Exportiere Kontakte als CSV](settings/userexport/contact) an. +Um die Liste der Kontakte *denen du folgst* zu exportieren, geht die [Einstellungen persönliche Daten exportieren](settings/userexport) und klicke den [Exportiere Kontakte als CSV](settings/userexport/contact) an. ## Import der gefolgten Kontakte @@ -17,6 +17,6 @@ Hier kannst du die CSV Datei auswählen und hoch laden. ### Unterstütztes Datei Format Die CSV Datei *muss* mindestens eine Spalte beinhalten. -In der ersten Spalte der Tabelle sollte *sollte* entweder das Handle oder die URL des gefolgten Kontakts. +In der ersten Spalte der Tabelle *sollte* entweder das Handle oder die URL des gefolgten Kontakts. (Ein Kontakt pro Zeile.) Alle anderen Spalten der CSV Datei werden beim Importieren ignoriert. diff --git a/doc/de/faq-admin.md b/doc/de/faq-admin.md index 1e05405db8..66c41fa15a 100644 --- a/doc/de/faq-admin.md +++ b/doc/de/faq-admin.md @@ -1,5 +1,4 @@ -Häufig gestellte Fragen (Admin) - FAQ -============== +# Häufig gestellte Fragen (Admin) - FAQ * [Zur Startseite der Hilfe](help) @@ -11,7 +10,7 @@ Häufig gestellte Fragen (Admin) - FAQ -### Kann ich mehrere Domains mit den selben Dateien aufsetzen? +## Kann ich mehrere Domains mit den selben Dateien aufsetzen? Ja, das ist möglich. Es ist allerdings nicht möglich, eine Datenbank durch zwei Domains zu nutzen. @@ -19,7 +18,7 @@ Solange Du Deine config/local.config.php allerdings so einrichtest, dass das Sys Alle Cache-Aspekte und der Zugriffsschutz können pro Instanz konfiguriert werden. -### Wo kann ich den Quellcode von Friendica, Addons und Themes finden? +## Wo kann ich den Quellcode von Friendica, Addons und Themes finden? Du kannst den Friendica-Quellcode [hier](https://github.com/friendica/friendica) finden. Dort findest Du immer die aktuellste stabile Version von Friendica. @@ -30,12 +29,12 @@ Addons findest Du auf [dieser Seite](https://github.com/friendica/friendica-addo Wenn Du neue Themen suchst, findest Du sie auf [github.com/bkil/friendica-themes](https://github.com/bkil/friendica-themes). -### Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden? +## Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden? Bitte aktualisiere deine E-Mail Adresse in der config/local.config.php Datei. -### Kann es mehr als einen Admin auf einer Friendica Instanz geben? +## Kann es mehr als einen Admin auf einer Friendica Instanz geben? Ja. Du kannst in der config/local.config.php Datei mehrere E-Mail Adressen auflisten. @@ -46,7 +45,7 @@ Die aufgelisteten Adressen werden wie folgt durch Kommas voneinander getrennt: ``` -### Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun? +## Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun? Rufe bitte im Admin Panel den Punkt [DB Updates](/admin/dbsync/) auf und folge dem Link *Datenbank Struktur überprüfen*. Damit wird ein Hintergrundprozess gestartet der die Struktur deiner Datenbank überprüft und gegebenenfalls aktualisiert. diff --git a/doc/de/faq.md b/doc/de/faq.md index 53c70c99d3..ce477b2f59 100644 --- a/doc/de/faq.md +++ b/doc/de/faq.md @@ -1,5 +1,4 @@ -Häufig gestellte Fragen - FAQ -============== +# Häufig gestellte Fragen - FAQ * [Zur Startseite der Hilfe](help) @@ -16,7 +15,7 @@ Häufig gestellte Fragen - FAQ -### Wo finde ich Hilfe? +## Wo finde ich Hilfe? Wenn Du Probleme mit Deiner Friendica-Seite hast, dann kannst Du die Community in der [Friendica-Support-Gruppe](https://forum.friendi.ca/profile/helpers) fragen. Wenn Du Deinen Account nicht nutzen kannst, kannst Du einen Account auf einer öffentlichen Seite ([Liste](https://dir.friendica.social/servers)) nutzen. @@ -36,7 +35,7 @@ Wenn du dir keinen weiteren Friendica Account einrichten willst, kannst du auch ---> -### Warum erhalte ich Warnungen über fehlende Zertifikate? +## Warum erhalte ich Warnungen über fehlende Zertifikate? Manchmal erhältst Du eine Browser-Warnung über fehlende Zertifikate. Diese Warnungen können drei Gründe haben: @@ -49,7 +48,7 @@ Diese Warnungen können drei Gründe haben: *(SSL (Secure Socket Layer) ist eine Technologie, die Daten auf ihrem Weg zwischen zwei Computern verschlüsselt.)* -Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch letsencrypt) oder kreiere Dein eigenes (nicht empfohlen). +Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch LetsEncrypt) oder kreiere Dein eigenes (nicht empfohlen). [Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/ssl) Sei Dir bewusst, dass Browser-Warnungen über Sicherheitslücken etwas sind, wodurch neue Nutzer schnell das Vertrauen in das gesamte Friendica-Projekt verlieren können. @@ -66,7 +65,7 @@ Einige erlauben die Nutzung von freien Zertifikaten oder lassen Dich ihre eigene Andere erlauben nur kostenpflichtige Zertifikate als eigenes Angebot bzw. von anderen Anbietern. -### Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen? +## Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen? Bilder können direkt im [Beitragseditor](help/text-editor) vom Computer hochgeladen werden. Eine Übersicht aller Bilder, die auf Deinem Server liegen, findest Du unter deineSeite.de/profile/profilname/photos. @@ -79,7 +78,7 @@ Deshalb eignet sich diese Methode vor allem für Office-Dateien oder gepackte Da Wer hingegen Dateien über Dropbox, über eine auf dem eigenen Server installierte Owncloud oder über einen anderen [Filehoster](http://en.wikipedia.org/wiki/Comparison_of_file_hosting_services) einfügen will, verwendet den Link-Button. Wenn Du mit dem Link-Button (Ketten-Symbol) URLs zu anderen Seiten einfügst, versucht Friendica eine kurze Zusammenfassung als Vorschau abzurufen. -Manchmal klappts das nicht ... dann verlinke den Beitrag einfach per [url=http://example.com]freigewählter Name[/url] im Editor. +Manchmal klappt das nicht ... dann verlinke den Beitrag einfach per [url=http://example.com]freigewählter Name[/url] im Editor. Video- und Audiodateien können zwar in Beiträge eingebunden werden, allerdings geht das nicht über einen direkten Upload im Editor wie bei Fotos. Du hast zwei Möglichkeiten: @@ -88,19 +87,19 @@ Du hast zwei Möglichkeiten: 2. Wenn Du Zugang zu einem eigenen Server hast, kannst Deine Multimediadatei per FTP dort hochladen und beim Video-/Audiobutton diese URL angeben. Dann wird das Video oder die Audiodatei direkt mit einem Player in Deinem Beitrag angezeigt. Friendica verwendet zur Einbettung HTML5. Das bedeutet, dass je nach Browser und Betriebssystem andere Formate unterstützt werden, darunter WebM, MP4, MP3 und Ogg. Eine Tabelle findest Du bei Wikipedia ([Video](http://en.wikipedia.org/wiki/HTML5_video), [Audio](http://en.wikipedia.org/wiki/HTML5_audio)). -Zum Konvertieren von Videos in das lizenfreie Videoformat WebM gibt es unter Windows das kostenlose Programm [Xmedia-Recode](http://www.xmedia-recode.de/). +Zum Konvertieren von Videos in das lizenzfreie Videoformat WebM gibt es unter Windows das kostenlose Programm [Xmedia-Recode](http://www.xmedia-recode.de/). -### Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben? +## Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben? Ja. Auf Deiner ["Profile verwalten/editieren"-Seite](../profiles) wählst Du zunächst das gewünschte Profil aus. -Anschließend siehst Du eine Seite mit allen Infos zu diesem Profil. +Anschließend siehst Du eine Seite mit allen Informationen zu diesem Profil. Klicke nun oben auf den Link "Profilbild ändern" und lade im nächsten Fenster ein Bild von Deinem PC hoch. Um Deine privaten Daten zu schützen, wird in Beiträgen nur das Bild aus Deinem öffentlichen Profil angezeigt. -### Wie kann ich Friendica in einer bestimmten Sprache ansehen? +## Wie kann ich Friendica in einer bestimmten Sprache ansehen? Die Sprache des Friendica Interfaces kann durch den `lang` Parameter un der URL beeinflusst werden. Das Argument des Parameters ist ein [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) Code. @@ -115,7 +114,7 @@ auf Deutsch: https://social.example.com/profile/example?lang=de. -### Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten? +## Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten? Wir verhindern direkte Kommunikation mit blockierten Kontakten. Sie gehören nicht zu den Empfängern beim Versand von Beiträgen und deren Beiträge werden auch nicht importiert. @@ -134,11 +133,11 @@ Dabei werden auch Kommentare dieser Person in Beiträgen Deiner Freunde blockier Ein archivierter Kontakt bedeutet, dass Kommunikation nicht möglich ist und auch nicht versucht wird (das ist z.B. sinnvoll, wenn eine Person zu einem neuen Server gewechselt ist und das alte Profil gelöscht hat). Anders als beim Blockieren werden existierende Beiträge, die vor der Archivierung erstellt wurden, weiterhin angezeigt. -Ein versteckter Kontakt wird in keiner "Freundeliste" erscheinen (außer für dich). -Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in Deiner Liste ist. +Ein versteckter Kontakt wird in keiner "Freundesliste" erscheinen (außer für dich). +Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in deiner Liste ist. -### Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht? +## Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht? Wenn Du Deinen Account löschst, wird sofort der gesamte Inhalt auf Deinem Server gelöscht und ein Löschbefehl an alle Deine Kontakte verschickt. Dadurch wirst Du ebenfalls aus dem globalen Verzeichnis gelöscht. @@ -146,18 +145,18 @@ Dieses Vorgehen setzt voraus, dass Dein Profil für 24 Stunden weiterhin "teilwe Wir können also Dein Profil blockieren und es so erscheinen lassen, als wären alle Daten sofort gelöscht, allerdings warten wir 24 Stunden (bzw. bis alle Deine Kontakte informiert wurden), bevor wir die Daten auch physikalisch löschen. -### Kann ich einem Hashtag folgen? +## Kann ich einem Hashtag folgen? Ja. Füge die Tags zu Deinen gespeicherten Suchen hinzu, sie werden automatisch auf der Netzwerk-Seite auftauchen. Bitte beachte, dass Deine Antworten auf solche Posts aus technischen Gründen nicht unter dem "Persönlich"-Reiter auf der Netzwerk-Seite und der gesamte Thread nicht per API zu sehen sind. -### Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen? +## Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen? Wenn Du die Beiträge Deines Accounts mit RSS teilen willst, dann kannst Du einen der folgenden Links nutzen: -#### RSS-Feed Deiner Beiträge +### RSS-Feed Deiner Beiträge deineSeite.de/feed/[profilname]/posts @@ -165,7 +164,7 @@ Beispiel: Friendica Support https://forum.friendi.ca/feed/helpers/posts -#### RSS-Feed all deiner Beiträge und Antworten +### RSS-Feed all deiner Beiträge und Antworten deineSeite.de/dfrn_poll/feed/[profilname]/comments @@ -173,18 +172,18 @@ Beispiel: Friendica Support https://forum.friendi.ca/feeds/helpers/comments -#### RSS-Feed all deiner Aktivitäten +### RSS-Feed all deiner Aktivitäten deineSeite.de/feed/[profilname]/ -### Gibt es Clients für Friendica? +## Gibt es Clients für Friendica? Friendica unterstützt [Mastodon API](help/api-mastodon) und [Twitter API | gnusocial](help/api). Das bedeutet, du kannst einge der Mastodon und Twitter Clients für Friendica verwenden. Die verfügbaren Features sind Abhängig vom Client, so dass diese teils unterschiedlich sein können. -#### Android +### Android * [AndStatus](http://andstatus.org) ([F-Droid](https://f-droid.org/repository/browse/?fdid=org.andstatus.app), [Google Play](https://play.google.com/store/apps/details?id=org.andstatus.app)) * [B4X for Pleroma & Mastodon](https://github.com/AnywhereSoftware/B4X-Pleroma) @@ -202,21 +201,21 @@ Die verfügbaren Features sind Abhängig vom Client, so dass diese teils untersc * [twitlatte](https://github.com/moko256/twitlatte) * [Yuito](https://github.com/accelforce/Yuito) -#### SailfishOS +### SailfishOS * [Friendly](https://openrepos.net/content/fabrixxm/friendly#comment-form) -#### iOS +### iOS -* [B4X for Pleroma & Mastodon](https://www.b4x.com/) ([AppStore](https://apps.apple.com/app/b4x-pleroma/id1538396871), [GitHub](https://github.com/AnywhereSoftware/B4X-Pleroma)) -* [Fedi](https://fediapp.com) ([AppStore](https://apps.apple.com/de/app/fedi-for-pleroma-and-mastodon/id1478806281)) -* [Mastodon](https://joinmastodon.org/apps)([AppStore](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) -* [Roma](https://www.roma.rocks/)([AppStore](https://apps.apple.com/de/app/roma-for-pleroma-and-mastodon/id1445328699)) -* [Stella*](https://www.stella-app.net/) ([AppStore](https://apps.apple.com/us/app/stella-for-mastodon-twitter/id921372048)) -* [Tooot](https://tooot.app/) ([AppStore](https://apps.apple.com/app/id1549772269), [GitHub](https://github.com/tooot-app)), Datensammlung (nicht mit Identität verknüpft) -* [Tootle](https://mastodon.cloud/@tootleapp) ([AppStore](https://apps.apple.com/de/app/tootle-for-mastodon/id1236013466)), letztes update: 2020 +* [B4X for Pleroma & Mastodon](https://www.b4x.com/) ([App Store](https://apps.apple.com/app/b4x-pleroma/id1538396871), [GitHub](https://github.com/AnywhereSoftware/B4X-Pleroma)) +* [Fedi](https://fediapp.com) ([App Store](https://apps.apple.com/de/app/fedi-for-pleroma-and-mastodon/id1478806281)) +* [Mastodon](https://joinmastodon.org/apps)([App Store](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) +* [Roma](https://www.roma.rocks/)([App Store](https://apps.apple.com/de/app/roma-for-pleroma-and-mastodon/id1445328699)) +* [Stella*](https://www.stella-app.net/) ([App Store](https://apps.apple.com/us/app/stella-for-mastodon-twitter/id921372048)) +* [Tooot](https://tooot.app/) ([App Store](https://apps.apple.com/app/id1549772269), [GitHub](https://github.com/tooot-app)), Datensammlung (nicht mit Identität verknüpft) +* [Tootle](https://mastodon.cloud/@tootleapp) ([App Store](https://apps.apple.com/de/app/tootle-for-mastodon/id1236013466)), letztes update: 2020 -#### Linux +### Linux * [Choqok](https://choqok.kde.org) * [Whalebird](https://whalebird.social) @@ -224,12 +223,12 @@ Die verfügbaren Features sind Abhängig vom Client, so dass diese teils untersc * [Toot](https://toot.readthedocs.io/en/latest/) * [Tootle](https://github.com/bleakgrey/tootle) -#### macOS +### macOS -* [Mastonaut](https://mastonaut.app/) ([AppStore](https://apps.apple.com/us/app/mastonaut/id1450757574)), kostet ~8€ -* [Whalebird](https://whalebird.social/en/desktop/contents) ([AppStore](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) +* [Mastonaut](https://mastonaut.app/) ([App Store](https://apps.apple.com/us/app/mastonaut/id1450757574)), kostet ~8€ +* [Whalebird](https://whalebird.social/en/desktop/contents) ([App Store](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Web +### Web * [Halcyon](https://www.halcyon.social/) * [Pinafore](https://github.com/nolanlawson/pinafore) diff --git a/doc/de/groups.md b/doc/de/groups.md index 52455cfa7f..5e7900113a 100644 --- a/doc/de/groups.md +++ b/doc/de/groups.md @@ -1,5 +1,4 @@ -Gruppen -===== +# Gruppen * [Zur Startseite der Hilfe](help) diff --git a/doc/de/guide.md b/doc/de/guide.md index fde9cb8ea4..021d48b25a 100644 --- a/doc/de/guide.md +++ b/doc/de/guide.md @@ -1,26 +1,25 @@ -Erste Schritte... -========== +# Erste Schritte... * [Zur Startseite der Hilfe](help) -Das Erste zum Anfang: geh sicher, dass du schon eingeloggt bist. -Wenn du noch nicht eingeloggt bist, kannst du das in dem Fenster unten machen. +Das Erste zum Anfang: geh sicher, dass du schon eingeloggt bist. +Wenn du noch nicht eingeloggt bist, kannst du das in dem Fenster unten machen. Sobald du eingeloggt bist (oder wenn du bereits eingeloggt bist), kannst du unten nun auf deine Profilseite schauen. -Hier sieht es ein wenig wie auf deiner Facebook-Seite aus. -Hier findest du alle deine Statusmeldungen und Nachrichten deiner Freunde, die direkt auf deine Seite ("Wall") geschrieben haben. -Um deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. -Wenn du das machst, vergrößert sich die Box. -Nun kannst du einige Formatierungsoptionen wie Fett, kursiv, unterstrichen auswählen und ebenfalls Bilder und Links hinzufügen. -Unten findest du in diesem Feld weitere Links, mit denen du Bilder und Dateien von deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. -Außerdem kannst du hier eintragen, wo du gerade bist. +Hier sieht es ein wenig wie auf deiner Facebook-Seite aus. +Hier findest du alle deine Statusmeldungen und Nachrichten deiner Freunde, die direkt auf deine Seite ("Wall") geschrieben haben. +Um deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. +Wenn du das machst, vergrößert sich die Box. +Nun kannst du einige Formatierungsoptionen wie Fett, kursiv, unterstrichen auswählen und ebenfalls Bilder und Links hinzufügen. +Unten findest du in diesem Feld weitere Links, mit denen du Bilder und Dateien von deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. +Außerdem kannst du hier eintragen, wo du gerade bist. -Wenn du deinen Beitrag ("Post") geschrieben hast, kannst du auf das "Schloss"-Symbol klicken und festlegen, wer deinen Beitrag sehen kann. -Wenn du dieses Symbol nicht anklickst, ist dein Beitrag öffentlich. +Wenn du deinen Beitrag ("Post") geschrieben hast, kannst du auf das "Schloss"-Symbol klicken und festlegen, wer deinen Beitrag sehen kann. +Wenn du dieses Symbol nicht anklickst, ist dein Beitrag öffentlich. Das bedeutet, dass jeder, der dein Profil ansieht, der auf dem "Community"-Tab deines Servers oder auf dem "Netzwerk"-Tab ("Beiträge deiner Kontakte") eines befreundeten Kontakts ist, den Beitrag sehen kann. -Probiere es doch einfach mal aus. Wenn du fertg bist, schauen wir uns den "Netzwerk"-Tab an. +Probiere es doch einfach mal aus. Wenn du fertg bist, schauen wir uns den "Netzwerk"-Tab an. diff --git a/doc/de/home.md b/doc/de/home.md index d03848b4a4..d11f6407e3 100644 --- a/doc/de/home.md +++ b/doc/de/home.md @@ -1,11 +1,10 @@ -Hilfe -===== +# Hilfe **Dokumentation für Benutzer** * Allgemeine Funktionen - Erste Schritte * [Account - Basics](help/account-basics) - * [Schnellstart für neue Benutzer](help/quick-start-guide) + * [Schnellstart für neue Benutzer](help/quick-start/guide) * [Beiträge erstellen](help/text-editor) * [Referenz der BBCode Elemente](help/bbcode) * [Beiträge kommentieren, einordnen und löschen](help/text-comment) diff --git a/doc/de/improve-performance.md b/doc/de/improve-performance.md index df90437e74..86403d53d0 100644 --- a/doc/de/improve-performance.md +++ b/doc/de/improve-performance.md @@ -1,5 +1,4 @@ -How-to: Performance verbessern -========== +# How-to: Performance verbessern * [Zur Startseite der Hilfe](help) @@ -9,27 +8,25 @@ Eine kleine Anleitung, um die Performance einer Friendica-Seite zu verbessern. Wenn du Fragen zu den folgenden Anweisungen oder zu anderen Themen hast, dann kannst du jederzeit beim Friendica-Support unter https://forum.friendi.ca/profile/helpers nachfragen. -Systemeinstellungen ---------------- +## Systemeinstellungen -Geh auf /admin/site in deinem System und ändere die folgenden Werte: +Geh auf `/admin/site` in deinem System und ändere die folgenden Werte: setze "Qualität des JPEG Bildes" auf 50. -Dieser Wert reduziert die Daten, die vom Server an den Client geschickt werden. +Dieser Wert reduziert die Daten, die vom Server an den Client geschickt werden. 50 ist ein Wert, der die Bildqualität nicht zu stark beeinflusst. setze "Intervall zum Vervollständigen von OStatus Unterhaltungen" auf "niemals" -Wenn du viele OStatus-Kontakte hast, dann kann die Vervollständigung von Unterhaltungen sehr zeitraubend sein. +Wenn du viele OStatus-Kontakte hast, dann kann die Vervollständigung von Unterhaltungen sehr zeitraubend sein. Der Nachteil: Du siehst nicht jede Antwort einer OStatus-Unterhaltung. Aus diesem Grund ist die Option "Beim Empfang von Nachrichten" in der Regel ein guter Kompromiss. setze "Nutze MySQL full text engine". Wenn du MyISAM (Standardeinstellung) oder InnoDB mit MariaDB 10 nutzt, dann beschleunigt dies die Suche. -Addons --------- +## Addons Aktiviere die folgenden Addons: @@ -55,8 +52,7 @@ Wenn es aktiviert ist, dann siehst du Werte wie die folgenden auf jeder deiner S Diese Werte zeigen deine Performance-Probleme. -Webserver ----------- +## Webserver Wenn du einen Apache-Webserver nutzt, aktiviere bitte die folgenden Module: @@ -80,7 +76,7 @@ Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_ Dieses Modul komprimiert den Datenverkehr (Traffic) zwischen dem Webserver und dem Client. -Aktiviere das Modul "mod_deflate" durch die Eingabe "a2enmod deflate" als root. +Aktiviere das Modul `mod_deflate` durch die Eingabe `a2enmod deflate` als root. Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_deflate.html @@ -89,9 +85,9 @@ Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_ **FCGI** -Wenn du Apache nutzt, dann denk darüber nach, FCGI zu nutzen. +Wenn du Apache nutzt, dann denk darüber nach, FCGI zu nutzen. Wenn du eine Debian-basierte Distribution nutzt, dann wirst du die Pakete "php5-cgi" und "libapache2-mod-fcgid" benötigen. -Nutze externe Dokumente, um eine detailiertere Erklärung für die Einrichtung eines Systems auf FCGI-Basis zu erhalten. +Nutze externe Dokumente, um eine detailliertere Erklärung für die Einrichtung eines Systems auf FCGI-Basis zu erhalten. ### Database diff --git a/doc/de/install.md b/doc/de/install.md index 205127e34e..46372f8a10 100644 --- a/doc/de/install.md +++ b/doc/de/install.md @@ -1,9 +1,8 @@ -Friendica Installation -========== +# Friendica Installation * [Zur Startseite der Hilfe](help) -Wir haben hart daran gearbeitet, um Friendica auf vorgefertigten Hosting-Plattformen zum Laufen zu bringen - solche, auf denen auch Wordpress Blogs und Drupal-Installationen laufen. +Wir haben hart daran gearbeitet, um Friendica auf vorgefertigten Hosting-Plattformen zum Laufen zu bringen - solche, auf denen auch WordPress Blogs und Drupal-Installationen laufen. Wir bieten eine manuelle und eine automatische Installation an. Aber bedenke, dass Friendica mehr als eine einfache Webanwendung ist. Es handelt sich um ein komplexes Kommunikationssystem, das eher an einen Email-Server erinnert als an einen Webserver. @@ -12,7 +11,7 @@ Diese Funktionalität benötigt ein wenig mehr als die normalen Blogs. Nicht jeder PHP/MySQL-Hosting-Anbieter kann Friendica unterstützen. Viele hingegen können es. Aber **bitte** prüfe die Voraussetzungen deines Servers vor der Installation. -Wenn dir Fehler während der Installation auffallen, sag uns bitte über [Helper](http://forum.friendi.ca/profile/helpers) oder die [Entwickler Gruppe](https://forum.friendi.ca/profile/developers) Bescheid oder [erstelle ein Issue](https://github.com/friendica/friendica/issues). +Wenn dir Fehler während der Installation auffallen, sag uns bitte über [Helper](https://forum.friendi.ca/profile/helpers) oder die [Entwickler Gruppe](https://forum.friendi.ca/profile/developers) Bescheid oder [erstelle ein Issue](https://github.com/friendica/friendica/issues). Gib uns bitte so viele Infos zu deinem System, wie du kannst, und beschreibe den Fehler mit allen Details und Fehlermeldungen, so dass wir den Fehler zukünftig verhindern können. Aufgrund der großen Anzahl an verschiedenen Betriebssystemen und PHP-Plattformen haben wir nur geringe Kapazitäten, um deine PHP-Installation zu debuggen oder fehlende Module zu ersetzen, aber wir tun unser Bestes, um allgemeine Code-Fehler zu beheben. @@ -21,10 +20,9 @@ Dinge verändern sich und einige deiner Freunde haben möglicherweise Probleme, Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben. -Requirements ---- +## Requirements -* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst +* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale `.htaccess`-Datei nutzen kannst * PHP 7.4+ * PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei * Curl, GD, GMP, PDO, mbstrings, MySQLi, hash, xml, zip, IntlChar, IDN und OpenSSL-Erweiterung @@ -35,8 +33,7 @@ Requirements * die Möglichkeit, wiederkehrende Aufgaben mit cron (Linux/Mac) oder "Scheduled Tasks" einzustellen (Windows) [Beachte: andere Optionen sind in Abschnitt 7 dieser Dokumentation zu finden] * Installation in einer Top-Level-Domain oder Subdomain (ohne eine Verzeichnis/Pfad-Komponente in der URL) wird bevorzugt. Verzeichnispfade sind für diesen Zweck nicht so günstig und wurden auch nicht ausführlich getestet. -Installation ---- +## Installation ### Alternative Wege um Friendica zu Installieren @@ -56,38 +53,44 @@ Entpacke die Friendica-Daten in das Quellverzeichnis (root) des Dokumentenbereic Wenn du die Möglichkeit hierzu hast, empfehlen wir dir "git" zu nutzen, um die Daten direkt von der Quelle zu klonen, statt die gepackte .tar- oder .zip-Datei zu nutzen. Das macht die Aktualisierung wesentlich einfacher. Der Linux-Code, mit dem man die Dateien direkt in ein Verzeichnis wie "meinewebseite" kopiert, ist - - git clone https://github.com/friendica/friendica.git -b stable mywebsite - cd mywebsite - bin/composer.phar run install:prod +```sh +git clone https://github.com/friendica/friendica.git -b stable mywebsite +cd mywebsite +bin/composer.phar run install:prod +``` Stelle sicher, dass der Ordner *view/smarty3* existiert and von dem Webserver-Benutzer beschreibbar ist - - mkdir view/smarty3 - chmod 775 view/smarty3 +```sh +mkdir view/smarty3 +chmod 775 view/smarty3 +``` Falls Addons installiert werden sollen: Gehe in den Friendica-Ordner - - cd mywebsite +```sh +cd mywebsite +``` Und die Addon Repository klonst: - - git clone https://github.com/friendica/friendica-addons.git -b stable addon +```sh +git clone https://github.com/friendica/friendica-addons.git -b stable addon +``` Um das Addon-Verzeichnis aktuell zu halten, solltest du in diesem Pfad ein "git pull"-Befehl eintragen +```sh +cd meinewebseite/addon +git pull +``` - cd meinewebseite/addon - git pull - -Wenn du den Verzeichnispfad auf deinen Webserver kopierst, dann stelle sicher, dass du auch die .htaccess kopierst, da "Punkt"-Dateien oft versteckt sind und normalerweise nicht direkt kopiert werden. +Wenn du den Verzeichnispfad auf deinen Webserver kopierst, dann stelle sicher, dass du auch die `.htaccess` kopierst, da "Punkt"-Dateien oft versteckt sind und normalerweise nicht direkt kopiert werden. Wenn du die Entwickler Version von Friendica verwenden möchtest kannst du auf den develop Branch im git Repository wechseln. Dies tust du mit den folgenden Befehlen - - git checkout develop - bin/composer.phar run install:prod - cd addon - git checkout develop +```sh +git checkout develop +bin/composer.phar run install:prod +cd addon +git checkout develop +``` Die Entwickler Version kann nach einem fehlerhaften Commit vorübergehend Probleme haben oder gar nicht mehr funktionieren. Sollte dir so etwas passieren, lass es uns bitte wissen, damit der Fehler behoben werden kann. @@ -101,8 +104,9 @@ Friendica benötigt die Berechtigungen um neue Felder in dieser Datenbank zu ert Mit neueren Versionen von MySQL (5.7.17+) musst du den `sql_mode` zu `''` (blank) setzen. Benutze diese Einstellung, wenn der Installer nicht in der Lage ist, die Tabellen aufgrund eines Timestamp-Format Problems zu erstellen. Falls dem so ist, finde den `[mysqld]` Bereich in deiner `my.conf` Datei und füge diese Zeile hinzu: - - sql_mode = '' +``` +sql_mode = '' +``` Starte MySQL dann neu und es sollte klappen. @@ -126,39 +130,42 @@ Du kannst bei Bedarf die Datei config/local.config.php verschieben/umbenennen un ### Option B: Starte das automatische Installationsscript Es existieren folgende Varianten zur automatischen Installation von Friendica: -- Eine vorgefertigte Konfigurationsdatei erstellen (z.B. `prepared.config.php`) -- Verwendung von Umgebungsvariablen (z.B. `MYSQL_HOST`) -- Verwendung von Optionen (z.B. `--dbhost `) +- Eine vorgefertigte Konfigurationsdatei erstellen (z.B. `prepared.config.php`) +- Verwendung von Umgebungsvariablen (z.B. `MYSQL_HOST`) +- Verwendung von Optionen (z.B. `--dbhost `) Umgebungsvariablen und Optionen können auch kombiniert werden. Dabei ist jedoch darauf zu achten, dass etwaige Optionen immer die zugehörigen Umgebungsvariablen überschreiben. Für mehr Informationen kannst du diese Option verwenden: - - bin/console autoinstall -v +```sh +bin/console autoinstall -v +``` Falls du alle optionalen Checks ausfürehn lassen möchtest, benutze diese Option: - - bin/console autoinstall -a +```sh +bin/console autoinstall -a +``` *Wenn* die automatisierte Installation aus irgendeinem Grund fehlschlägt, dann prüfe das Folgende: -* Existiert die `config/local.config.php`? Falls ja, wird die automatisierte Installation nicht gestartet. -* Sind Einstellungen in der `config/local.config.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. -* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. +* Existiert die `config/local.config.php`? Falls ja, wird die automatisierte Installation nicht gestartet. +* Sind Einstellungen in der `config/local.config.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. +* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. #### B.1: Konfigurationsdatei Für diese Variante muss ein Konfigurationsdatei bereits vor der Installation fertig definiert sein (z.B. [local-sample.config.php](config/local-sample.config.php). Gehe im Anschluss in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: - - bin/console autoinstall -f +```sh +bin/console autoinstall -f +``` #### B.2: Umgebungsvariablen Es existieren Zwei Arten von Umgebungsvariablen in Friendica: -- Jene, die auch im normalen Betrieb verwendet werden können (derzeit ausschließlich **Datenbank Einstellungen**) -- Jene, die nur während der Installation verwedent werden können (im normalen Betrieb werden sie ignoriert) +- Jene, die auch im normalen Betrieb verwendet werden können (derzeit ausschließlich **Datenbank Einstellungen**) +- Jene, die nur während der Installation verwedent werden können (im normalen Betrieb werden sie ignoriert) Umgebungsvariablen können auch durch adäquate Optionen (z.B. `--dbhost `)übersteuert werden. @@ -166,57 +173,62 @@ Umgebungsvariablen können auch durch adäquate Optionen (z.B. `--dbhost ` Der Host der MySQL/MariaDB Datenbank (env `MYSQL_HOST`) -- `-p|--dbport ` Der Port der MySQL/MariaDB Datenbank (env `MYSQL_PORT`) -- `-U|--dbuser ` Der Benutzername des MySQL/MariaDB Datenbanklogins (env `MYSQL_USER` or `MYSQL_USERNAME`) -- `-P|--dbpass ` Das Passwort der MySQL/MariaDB Datenbanklogins (env `MYSQL_PASSWORD`) -- `-d|--dbdata ` Der Name der MySQL/MariaDB Datenbank (env `MYSQL_DATABASE`) -- `-b|--phppath ` Der Pfad zur PHP-Datei (env `FRIENDICA_PHP_PATH`) -- `-A|--admin ` Die Admin E-Mail Adresse dieses Friendica Knotens (env `FRIENDICA_ADMIN_MAIL`) -- `-T|--tz ` Die Zeitzone von Friendica (env `FRIENDICA_TZ`) -- `-L|--lang ` Die Sprache von Friendica (env `FRIENDICA_LANG`) +- `-H|--dbhost ` Der Host der MySQL/MariaDB Datenbank (env `MYSQL_HOST`) +- `-p|--dbport ` Der Port der MySQL/MariaDB Datenbank (env `MYSQL_PORT`) +- `-U|--dbuser ` Der Benutzername des MySQL/MariaDB Datenbanklogins (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` Das Passwort der MySQL/MariaDB Datenbanklogins (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` Der Name der MySQL/MariaDB Datenbank (env `MYSQL_DATABASE`) +- `-b|--phppath ` Der Pfad zur PHP-Datei (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` Die Admin E-Mail Adresse dieses Friendica Knotens (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` Die Zeitzone von Friendica (env `FRIENDICA_TZ`) +- `-L|--lang ` Die Sprache von Friendica (env `FRIENDICA_LANG`) Gehe in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: - - bin/console autoinstall [options] +```sh +bin/console autoinstall [options] +``` ### Einen Worker einrichten Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. Beispiel: - - cd /base/directory; /path/to/php bin/console.php worker +```sh +cd /base/directory; /path/to/php bin/console.php worker +``` Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben. Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System -`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker` +```crontab +*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +``` Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst. Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren. diff --git a/doc/de/installing-connectors.md b/doc/de/installing-connectors.md index 7d378e2374..25030da0c7 100644 --- a/doc/de/installing-connectors.md +++ b/doc/de/installing-connectors.md @@ -1,5 +1,4 @@ -Konnektoren installieren -================================================== +# Konnektoren installieren * [Zur Startseite der Hilfe](help) @@ -19,8 +18,7 @@ Andere Konnektoren, wie Bluesky, benötigen überhaupt keinen API-Schlüssel. Weitere Informationen zu den spezifischen Anforderungen findest du auf der Einstellungsseite des jeweiligen Addons, entweder auf der Verwaltungsseite oder auf der Benutzerseite. -Bluesky Jetstream ---- +## Bluesky Jetstream Um die Konnektivität mit Bluesky weiter zu verbessern, kann die „Jetstream“-Konnektivität aktiviert werden. Jetstream ist ein Dienst, der sich mit dem Bluesky-Firehose verbindet. diff --git a/doc/de/making-friends.md b/doc/de/making-friends.md index 041365103c..383d7f4a15 100644 --- a/doc/de/making-friends.md +++ b/doc/de/making-friends.md @@ -1,5 +1,4 @@ -Freunde finden -============== +# Freunde finden * [Zur Startseite der Hilfe](help) @@ -12,23 +11,23 @@ Das Verzeichnis ist in zwei Teile aufgeteilt. Wenn du auf den "Verzeichnis"-Button klickst, wirst du zunächst alle Mitglieder deines Servers sehen, die sich dazu entschlossen haben, angezeigt zu werden. Außerdem siehst du dort einen Link zum globalen Verzeichnis. Wenn du dich durch das globale Verzeichnis klickst, siehst du alle Nutzer weltweit auf allen Servern, die sich entschlossen haben, im Verzeichnis zu erscheinen. -Du wirst außerdem den Link "Show Community Groups" sehen, welcher dich zu Gruppen und Fan-Seiten führt. +Du wirst zudem den Link "Show Community Groups" sehen, welcher dich zu Gruppen und Fan-Seiten führt. Du verbindest dich mit Personen und Gruppen auf die gleiche Art, wobei Gruppen deine Anfrage automatisch annehmen, wohingegen ein Mensch dich erst manuell bestätigen muss. *Mit anderen Friendica-Nutzern verbinden* Besuche ihr Profil. Direkt unter dem Profilfoto ist das Wort "Verbinden" (bzw. "Connect" in einem englischsprachigem Profil). -Klicke drauf und du gelangst zur "Verbinden"-Seite. +Klicke darauf und du gelangst zur "Verbinden"-Seite. Dort wirst du nach deiner Identitätsadresse gefragt. Das ist nötig, damit die Seite dein Profil finden kann. *Was kommt in die Box?* Wenn deine Friendica-Seite "demo.friendica.com" heißt und dein Nutzername/Spitzname auf der Seite "bob" ist, dann wäre es "bob@demo.friendica.com". -Wie du siehst, sieht es wie eine Email-Adresse aus. +Wie du siehst, sieht es wie eine E-Mail-Adresse aus. Das ist beabsichtigt, da sich die Leute das so leichter merken können. -Du *kannst* auch die URL deiner Startseite eintragen, wie z.B. "http://demo.friendica.com/profile/bob", aber der Email-Adressen-Stil ist einfacher. +Du *kannst* auch die URL deiner Startseite eintragen, wie z.B. "http://demo.friendica.com/profile/bob", aber der E-Mail-Adressen-Stil ist einfacher. Wenn du die "Verbinden"-Seite bestätigt hast, kommst du zurück zu deiner Seite, um dort die Anfrage zu bestätigen. Wenn du das gemacht hast, können beide Seiten miteinander kommunizieren, um den Prozess abzuschließen (sobald dein neuer Freund die Anfrage bestätigt hat). @@ -45,7 +44,7 @@ Wenn du z.B. "bob" auf quitter.se (eine GNU Social-Seite) kennst, dann kannst du Tatsächlich kannst du jedem und jeder Website folgen, der/die einen Syndication-Feed (RSS/Atom etc.) zur Verfügung stellt. Wenn wir einen Informationsstrom und einen Namen dazu finden, können wir auch versuchen, uns damit zu verbinden. -Wenn du deine Email-Postfachverbindung auf deiner Einstellungsseite konfiguriert hast, dann kannst du die Email-Adresse jeder Person eintragen, die dir schon eine Nachricht an dein Postfach geschickt hat und bereits in deinem sozialen Stream erscheint. +Wenn du deine E-Mail-Postfachverbindung auf deiner Einstellungsseite konfiguriert hast, dann kannst du die E-Mail-Adresse jeder Person eintragen, die dir schon eine Nachricht an dein Postfach geschickt hat und bereits in deinem sozialen Stream erscheint. Du kannst diesen Personen außerdem von Friendica aus antworten. Leute können sich ebenfalls von anderen Netzwerken aus mit dir befreunden. diff --git a/doc/de/message-flow.md b/doc/de/message-flow.md index ef2a0a2715..58fbace5e7 100644 --- a/doc/de/message-flow.md +++ b/doc/de/message-flow.md @@ -1,14 +1,13 @@ -Friendica Nachrichtenfluss -============== +# Friendica Nachrichtenfluss * [Zur Startseite der Hilfe](help) -Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden. -Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen. +Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden. +Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen. Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/stable/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub). -Wenn eine Nachricht veröffentlicht wird, werden alle Übermittlungen an alle Netzwerke mit include/notifier.php durchgeführt, welche entscheidet, wie und an wen die Nachricht geliefert wird. +Wenn eine Nachricht veröffentlicht wird, werden alle Übermittlungen an alle Netzwerke mit include/notifier.php durchgeführt, welche entscheidet, wie und an wen die Nachricht geliefert wird. Diese Datei bindet dabei die lokale Bearbeitung aller Übertragungen ein inkl. dfrn-notify. mod/dfrn_notify.php handhabt die Rückmeldung (remote side) von dfrn-notify. @@ -22,40 +21,40 @@ PuSh-Feeds (pubsubhubbub) kommen via mod/pubsub.php an. DFRN-poll Feed-Imports kommen via src/Worker/OnePoll.php als geplanter Task an, das implementiert die lokale Bearbeitung (local side) des DFRN-Protokolls. -### Szenario #1. Bob schreibt eine öffentliche Statusnachricht +## Szenario #1. Bob schreibt eine öffentliche Statusnachricht -Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist. -Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub). -Wenn ein PuSH-Hub einsatzfähig ist, nutzen DFRN-Poll-Clients vorrangig die Informationen, die durch den PuSH-Kanal kommen. -Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwierigkeiten hat (das kann vorkommen, wenn der standardmäßige Google-Referenzhub genutzt wird). -Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen. +Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist. +Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub). +Wenn ein PuSH-Hub einsatzfähig ist, nutzen DFRN-Poll-Clients vorrangig die Informationen, die durch den PuSH-Kanal kommen. +Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwierigkeiten hat (das kann vorkommen, wenn der standardmäßige Google-Referenzhub genutzt wird). +Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen. Feeds, die via DFRN-Poll abgerufen werden, sind bbcode und können auch private Unterhaltungen enthalten, die vom Poller auf ihre Zugriffsrechte hin geprüft werden. -### Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk. +## Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk. -Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. -Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt. +Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. +Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt. Die PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen diese an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk. +## Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk. -Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. -Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt). -Die Nachrichten werden mit dfrn-notify übertragen. -PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. +Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. +Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt). +Die Nachrichten werden mit dfrn-notify übertragen. +PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk. +## Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk. -William nutzt salmon, um Bob über seine Antwort zu benachrichtigen. -Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist. -Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet). +William nutzt salmon, um Bob über seine Antwort zu benachrichtigen. +Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist. +Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet). PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack. +## Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack. -Die Nachricht wird sofort an Mary und Jack mit Hilfe von dfrn_notify geschickt. -Öffentliche Hubs werden nicht benachrichtigt. -Im Falle eines Timeouts wird eine erneute Verarbeitung angestoßen. -Antworten folgen dem gleichen Nachrichtenfluss wie öffentliche Antworten, allerdings werden die Hubs nicht darüber informiert, wodurch die Nachrichten niemals in öffentliche Feeds gelangen. +Die Nachricht wird sofort an Mary und Jack mithilfe von dfrn_notify geschickt. +Öffentliche Hubs werden nicht benachrichtigt. +Im Falle eines Timeouts wird eine erneute Verarbeitung angestoßen. +Antworten folgen dem gleichen Nachrichtenfluss wie öffentliche Antworten, allerdings werden die Hubs nicht darüber informiert, wodurch die Nachrichten niemals in öffentliche Feeds gelangen. Die komplette Unterhaltung ist nur für Mary und Jack in ihren durch dfrn-poll personalisierten Feeds verfügbar (und für niemanden sonst). diff --git a/doc/de/move-account.md b/doc/de/move-account.md index 2573113bba..a4fbd4ee75 100644 --- a/doc/de/move-account.md +++ b/doc/de/move-account.md @@ -1,17 +1,15 @@ -Accounts Umziehen -================= +# Accounts Umziehen * [Zur Startseite der Hilfe](help) - ! **Dies ist ein experimentelles Feature** **Wie man einen Account von einem Server zu einem anderen umzieht.** Unter "Einstellungen" -> "[Persönliche Daten exportieren](uexport)" aufrufen. "Account exportieren" anklicken und die Daten speichern. -Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. -Außerdem enthält sie deinen geheimen Schlüssel mit dem du dich deinen Kontakten gegenüber ausweist. +Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. +Außerdem enthält sie deinen geheimen Schlüssel, mit dem du dich deinen Kontakten gegenüber ausweist. **Speichere diese Datei an einem sicheren Ort**! @@ -24,11 +22,11 @@ Hier kann dies nur der Administrator selber durchführen. Lege auf dem neuen Server auf keinen Fall einen gleichnamigen Account an! user import muss anstelle des Registrierens verwendet werden. -Wähle die gesicherte Account Datei aus und klicke "Importieren". +Wähle die gesicherte Account-Datei aus und klicke "Importieren". -Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. +Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. An deine Friendica Kontakte wird außerdem eine Nachricht gesendet um sie über deine neue Adresse zu informieren. -Wenn deine Kontakte ihren Account auf einem aktuellen Server haben werden deine Kontaktdetails automatisch aktualisiert. +Wenn deine Kontakte ihren Account auf einem aktuellen Server haben, werden deine Kontaktdetails automatisch aktualisiert. Neuere Diaspora Server unterstützen ebenfalls eine Umzugsbenachrichtigung. diff --git a/doc/de/quick-start-finally.md b/doc/de/quick-start-finally.md deleted file mode 100644 index 748f600deb..0000000000 --- a/doc/de/quick-start-finally.md +++ /dev/null @@ -1,18 +0,0 @@ -... und zuletzt -=============== - -Und damit sind wir auch schon am Ende der Schnellstartanleitung. - -Hier sind noch einige weitere Dinge, die Dir den Start vereinfachen können. - -**Gruppen** - - -- Friendica Support - Probleme? Dann ist das der Platz, um zu fragen! - -**Dokumentation** - -- Zu weiteren Netzwerken verbinden -- Zur Startseite der Hilfe - - diff --git a/doc/de/quick-start/finally.md b/doc/de/quick-start/finally.md new file mode 100644 index 0000000000..7d5c94cccd --- /dev/null +++ b/doc/de/quick-start/finally.md @@ -0,0 +1,14 @@ +# ... und zuletzt + +Und damit sind wir auch schon am Ende der Schnellstartanleitung. + +Hier sind noch einige weitere Dinge, die Dir den Start vereinfachen können. + +**Gruppen** + +- [Friendica Support](https://forum.friendi.ca/profile/helpers) - Probleme? Dann ist das der Platz, um zu fragen! + +**Dokumentation** + +- [Zu weiteren Netzwerken verbinden](help/connectors) +- [Zur Startseite der Hilfe](help) diff --git a/doc/de/quick-start-groups-and-pages.md b/doc/de/quick-start/groups-and-pages.md similarity index 89% rename from doc/de/quick-start-groups-and-pages.md rename to doc/de/quick-start/groups-and-pages.md index 44079fd777..825349cdd2 100644 --- a/doc/de/quick-start-groups-and-pages.md +++ b/doc/de/quick-start/groups-and-pages.md @@ -1,5 +1,4 @@ -Gruppen und Seiten -========== +# Gruppen und Seiten * [Zur Startseite der Hilfe](help) @@ -19,8 +18,6 @@ Suche Dir einfach eine Gruppe und füge sie so hinzu, wie Du auch normale Freund Es gibt eine Menge Gruppen. Solltest Du beim Stöbern durch die vielen Gruppen nicht wieder hierher zurück finden, so nutze einfach den Link oben auf dieser Seite. -Wenn Du einige Gruppen hinzugefügt hast, gehe weiter zum nächsten Schritt. +Wenn Du einige Gruppen hinzugefügt hast, gehe [weiter zum nächsten Schritt](help/quick-start/finally). - - diff --git a/doc/de/quick-start-guide.md b/doc/de/quick-start/guide.md similarity index 88% rename from doc/de/quick-start-guide.md rename to doc/de/quick-start/guide.md index 41dc0c3102..f72a6b05d4 100644 --- a/doc/de/quick-start-guide.md +++ b/doc/de/quick-start/guide.md @@ -1,5 +1,4 @@ -Erste Schritte... -========== +# Erste Schritte... * [Zur Startseite der Hilfe](help) @@ -20,17 +19,15 @@ Wenn Du Deinen Beitrag ("Post") geschrieben hast, kannst Du auf das "Schloss"-Sy Wenn Du dieses Symbol nicht anklickst, ist Dein Beitrag öffentlich, bzw. es werden deine Grundeinstellungen verwendet, wenn diese nicht öffentlich sind. Ein öffentlicher Beitrag ist sichbar für -
          -
        • Besucher Deines Profils
        • -
        • Besucher Deiner "Gemeinschafts"-Seite
        • -
        • Besucher der Profile Deiner Kontakte
        • -
        • Suchmaschinen
        • -
        +- Besucher Deines Profils +- Besucher Deiner "Gemeinschafts"-Seite +- Besucher der Profile Deiner Kontakte +- Suchmaschinen + Auch wenn Du Deinen Server so konfiguriert hast, dass der Zugriff von außerhalb des Friendica-Netzwerks theoretisch nicht möglich ist, so ist Dein Beitrag über die Profile Deiner Kontakte sichtbar, wenn deren Knoten solche Zugriffe zulassen. -Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den "Netzwerk"-Tab an. +Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den ["Netzwerk"-Tab](help/quick-start/network) an. - diff --git a/doc/de/quick-start-making-new-friends.md b/doc/de/quick-start/making-new-friends.md similarity index 78% rename from doc/de/quick-start-making-new-friends.md rename to doc/de/quick-start/making-new-friends.md index 24fcbcc5dc..166f0201bc 100644 --- a/doc/de/quick-start-making-new-friends.md +++ b/doc/de/quick-start/making-new-friends.md @@ -1,10 +1,9 @@ -Neue Freunde finden -============== +# Neue Freunde finden * [Zur Startseite der Hilfe](help) Hier siehst Du die Kontaktvorschläge. -Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/quick-start/making-new-friends) und wieder hierher kommen. Diese Seite funktioniert in etwa wie die Seite für Kontaktvorschläge in Facebook. Jeder auf dieser Liste hat zugestimmt, als Kontaktvorschlag zu erscheinen. @@ -21,8 +20,6 @@ Jetzt, nachdem Du jemanden hinzugefügt hast, weißt Du vielleicht nicht mehr, w Klicke einfach auf den Link oben auf dieser Seite und Du gelangst zur Seite mit den Kontaktvorschlägen zurück, um weitere Personen hinzuzufügen. Du willst nicht einfach Personen hinzufügen, die du nicht kennst? -Kein Problem - an dieser Stelle kommen wir zu den Gruppen und Seiten. +Kein Problem - an dieser Stelle kommen wir zu den [Gruppen und Seiten](help/quick-start/groups-and-pages). - - diff --git a/doc/de/quick-start-network.md b/doc/de/quick-start/network.md similarity index 76% rename from doc/de/quick-start-network.md rename to doc/de/quick-start/network.md index c810010809..a77fbe498d 100644 --- a/doc/de/quick-start-network.md +++ b/doc/de/quick-start/network.md @@ -1,10 +1,9 @@ -Deine "Netzwerk"-Seite -============== +# Deine "Netzwerk"-Seite * [Zur Startseite der Hilfe](help) Dies ist Dein "Netzwerk"-Tab. -Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken, um wieder hierher zu kommen. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/quick-start/network), um wieder hierher zu kommen. Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. @@ -13,8 +12,6 @@ Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträg Du kannst ihre Beiträge von hier aus kommentieren, mitteilen, dass Du den Beitrag magst oder ablehnst (Daumen hoch, Daumen runter) oder die Profile durch einen Klick auf deren Namen besuchen und dort auf deren "Pinnwand" ("Wall") Nachrichten schreiben. Nun wollen wir diese Seite mit Inhalt füllen. -Der erste Schritt ist es, Leute zu Deinem Account hinzuzufügen. +Der erste Schritt ist es, [Leute zu Deinem Account hinzuzufügen](help/quick-start/making-new-friends). - - diff --git a/doc/de/readme.md b/doc/de/readme.md index a4e2bdec77..08fa5d79d8 100644 --- a/doc/de/readme.md +++ b/doc/de/readme.md @@ -1,9 +1,8 @@ -Friendica-doc-german -==================== +# Friendica-doc-german Friendica - doc - german -Hier findest du die deutsche Version der Friendica-Hilfedateien. -Es handelt sich um eine selbst erstellte, öffentlich freigegebene Arbeit mit dem Ziel, Friendica durch deutsche Hilfedateien für weitere Personen zugänglich zu machen, die dem Englischen nicht ausreichend mächtig sind. +Hier findest du die deutsche Version der Friendica-Hilfedateien. +Es handelt sich um eine selbst erstellte, öffentlich freigegebene Arbeit mit dem Ziel, Friendica durch deutsche Hilfedateien für weitere Personen zugänglich zu machen, die dem Englischen nicht ausreichend mächtig sind. Die Daten basieren auf dem offiziellen Friendica-Github https://github.com/friendica/friendica (Stand: 03.11.12) diff --git a/doc/de/remove-account.md b/doc/de/remove-account.md index 5cba208fea..60d5f46f22 100644 --- a/doc/de/remove-account.md +++ b/doc/de/remove-account.md @@ -1,5 +1,4 @@ -Accounts löschen -============== +# Accounts löschen * [Zur Startseite der Hilfe](help) @@ -7,17 +6,17 @@ Wir freuen uns nicht, wenn Leute Friendica verlassen, aber wenn du deinen Accoun [Lösche mich (http://NamederSeite/settings/removeme)](../settings/removeme) -in deinem Webbrowser. Du musst dabei eingeloggt sein. +in deinem Webbrowser. Du musst dabei eingeloggt sein. -Du wirst nach deinem Passwort gefragt, um die Anfrage zu bestätigen. +Du wirst nach deinem Passwort gefragt, um die Anfrage zu bestätigen. Wenn dieses mit deinem gespeichertem Passwort übereinstimmt, dann wird dein Account als "gelöscht" markiert. Dies passiert sofort und kann nicht rückgängig gemacht werden. -Die meisten Deiner Inhalte und Benutzerdaten werden kurzfristig danach durch Hintergrundprozesse gelöscht. +Die meisten deiner Inhalte und Benutzerdaten werden kurzfristig danach durch Hintergrundprozesse gelöscht. Parallel dazu senden wir eine Mitteilung an die Server deiner Kontakte, damit sie deine dort vorliegenden Daten ebenfalls löschen. Wir haben keinen Einfluss darauf, wie sorgfältig und ob überhaupt diese Systeme der Löschaufforderung nachgehen. -Aus technischen Gründen benötigen wir für die Übetragung dieser Mitteilung ein paar Benutzerdaten. +Aus technischen Gründen benötigen wir für die Übertragung dieser Mitteilung ein paar Benutzerdaten. Diese Daten werden dann nach einer Frist von etwa sieben Tagen ebenfalls gelöscht. Wir speichern deinen Benutzernamen dauerhaft, damit sich niemand einen Account unter deinem Spitznamen anlegen kann. diff --git a/doc/de/settings.md b/doc/de/settings.md index 0251195c28..68d639cb5f 100644 --- a/doc/de/settings.md +++ b/doc/de/settings.md @@ -334,10 +334,12 @@ Du solltest deshalb einen Dienst zur [log rotation](https://en.wikipedia.org/wik Normalerweise werden Fehler- und Warnmeldungen von PHP unterdrückt. Wenn du sie aktivieren willst, musst du folgendes in der `config/local.config.php` Datei eintragen um die Meldungen in die Datei `php.out` zu speichern - error_reporting(E_ERROR | E_WARNING | E_PARSE ); - ini_set('error_log','php.out'); - ini_set('log_errors','1'); - ini_set('display_errors', '0'); +``` +error_reporting(E_ERROR | E_WARNING | E_PARSE ); +ini_set('error_log','php.out'); +ini_set('log_errors','1'); +ini_set('display_errors', '0'); +``` Die Datei `php.out` muss vom Webserver schreibbar sein und sollte ebenfalls außerhalb der Webverzeichnisse liegen. Es kommt gelegentlich vor, dass nicht deklarierte Variablen referenziert werden, dehalb raten wir davon ab `E_NOTICE` oder `E_ALL` zu verwenden. @@ -366,13 +368,15 @@ Dies sind die Datenbank Einstellungen, die Administrator Accounts, der PHP Pfad Mit den folgenden Einstellungen kannst du die Zugriffsdaten für den Datenbank Server festlegen. - 'database' => [ - 'hostname' => 'localhost', - 'username' => 'mysqlusername', - 'password' => 'mysqlpassword', - 'database' => 'mysqldatabasename', - 'charset' => 'utf8mb4', - ], +``` +'database' => [ + 'hostname' => 'localhost', + 'username' => 'mysqlusername', + 'password' => 'mysqlpassword', + 'database' => 'mysqldatabasename', + 'charset' => 'utf8mb4', +], +``` Sollten alle der folgenden Environment-Variablen gesetzt sein, wird Friendica diese anstatt der vorher konfigurierten Werte nutzen. @@ -389,18 +393,22 @@ Normalerweise trifft dies auf den ersten Account zu, der nach der Installation a Die Liste der E-Mail Adressen kann aber einfach erweitert werden. Mit keiner der angegebenen E-Mail Adressen können weitere Accounts registriert werden. - 'config' => [ - 'admin_email' => 'you@example.com, buddy@example.com', - ], +``` +'config' => [ + 'admin_email' => 'you@example.com, buddy@example.com', +], +``` ## PHP Pfad Einige Prozesse von Friendica laufen im Hintergrund. Für diese Prozesse muss der Pfad zu der PHP Version gesetzt sein, die verwendet werden soll. - 'config' => [ - 'php_path' => '/usr/bin/php', - ], +``` +'config' => [ + 'php_path' => '/usr/bin/php', +], +``` ## Unterverzeichnis Konfiguration @@ -408,9 +416,11 @@ Man kann Friendica in ein Unterverzeichnis des Webservers installieren. Wir raten allerdings dringen davon ab, da es die Interoperabilität mit anderen Netzwerken (z.B. Diaspora, GNU Social, Hubzilla) verhindert. Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein weiteres Unterverzeichnis installieren, dann lautet die Konfiguration hierfür: - 'system' => [ - 'url' => 'https://example.com/tests/friendica', - ], +``` +'system' => [ + 'url' => 'https://example.com/tests/friendica', +], +``` ## Weitere Ausnahmen diff --git a/doc/de/ssl.md b/doc/de/ssl.md index 3d20cb5b1e..838a6b4116 100644 --- a/doc/de/ssl.md +++ b/doc/de/ssl.md @@ -1,5 +1,4 @@ -Friendica mit SSL nutzen -===================================== +# Friendica mit SSL nutzen * [Zur Startseite der Hilfe](help) @@ -47,9 +46,9 @@ Wenn ja, dann lies weiter. Wenn du einen eigenen Server betreibst und den Nameserver kontrollierst, könnte auch die Initiative "Let's encrypt" interessant für dich werden. Sie bietet nicht nur freie SSL Zertifikate sondern auch einen automatisierten Prozess zum Erneuern der Zertifikate. -Um letsencrypt Zertifikate verwenden zu können, musst du dir einen Client auf deinem Server installieren. -Eine Anleitung zum offiziellen Client findet du [hier](https://certbot.eff.org/). -Falls du dir andere Clients anschauen willst, kannst du einen Blick in diese [Liste von alternativen letsencrypt Clients](https://letsencrypt.org/docs/client-options/). +Um LetsEncrypt Zertifikate verwenden zu können, musst du dir einen Client auf deinem Server installieren. +Eine Anleitung zum offiziellen Client findest du [hier](https://certbot.eff.org/). +Falls du dir andere Clients anschauen willst, kannst du einen Blick in diese [Liste von alternativen LetsEncrypt Clients](https://letsencrypt.org/docs/client-options/). ## Webserver-Einstellungen @@ -62,32 +61,37 @@ Wenn du fertig bist, kannst du auf der Testseite [SSL-Labs](https://www.ssllabs. ## Friendica Konfigurieren -Wenn du deine Friendica Instanz über https erreichen kannst solltest du ein paar Einstellungen vornehmen um sicher zu stellen, dass deine Nutzer ausschließlich über https zugreifen können. +Wenn du deine Friendica Instanz über https erreichen kannst solltest du ein paar Einstellungen vornehmen um sicherzustellen, dass deine Nutzer ausschließlich über https zugreifen können. ### Webserver-Umleitungen Dies ist der einfachste Weg den Zugriff für die ganze Webseite abzusichern. -Jedes Mal wenn ein Nutzer Friendica aufruft wird er permanent vom Webserver auf die abgesicherte Seite umgeleitet. +Jedes Mal, wenn ein Nutzer Friendica aufruft wird er permanent vom Webserver auf die abgesicherte Seite umgeleitet. Wenn du den Apache Webserver verwendest, aktiviere die Module rewrite und ssl (bei einem Shared-Hosting Prider sollte dies bereits der Fall sein): - sudo a2enmod rewrite ssl +```sh +sudo a2enmod rewrite ssl +``` -und füge die folgenden Zeilen zur .htaccess Datei im Wurzelverzeichnis deiner Friendica Instanz hinzu: +und füge die folgenden Zeilen zur `.htaccess` Datei im Wurzelverzeichnis deiner Friendica Instanz hinzu: - RewriteEngine On - RewriteCond %{SERVER_PORT} 80 - RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` +RewriteEngine On +RewriteCond %{SERVER_PORT} 80 +RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` (Dank an [url=https://github.com/AlfredSK]AlfredSK[/url]). Bei nginx solltest du deinen Server folgendermaßen konfigurieren ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)): - - server { - listen 80; - server_name your.friendica.domain; - return 301 https://$server_name$request_uri; - } +``` +server { + listen 80; + server_name your.friendica.domain; + return 301 https://$server_name$request_uri; +} +``` ### SSL Einstellungen diff --git a/doc/de/tags-and-mentions.md b/doc/de/tags-and-mentions.md index 8ab5bb581d..c0851efe65 100644 --- a/doc/de/tags-and-mentions.md +++ b/doc/de/tags-and-mentions.md @@ -1,5 +1,4 @@ -Tags und Erwähnungen -================= +# Tags und Erwähnungen * [Zur Startseite der Hilfe](help) diff --git a/doc/de/text-comment.md b/doc/de/text-comment.md index c9203dfd4c..6c179b1f1f 100644 --- a/doc/de/text-comment.md +++ b/doc/de/text-comment.md @@ -1,11 +1,10 @@ -Beiträge kommentieren, einordnen und löschen -========================================================== +# Beiträge kommentieren, einordnen und löschen * [Zur Startseite der Hilfe](help) -Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, bestehende Beiträge einzuordnen und zu kommentieren. +Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, bestehende Beiträge einzuordnen und zu kommentieren. -Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. +Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. @@ -13,37 +12,37 @@ Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht ode Die einzelnen Symbole -post_thumbs_up.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag gefällt. +post_thumbs_up.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag gefällt. Falls du diese Eingabe zurücknehmen willst, klicke einfach ein zweites Mal auf das Symbol.

        -post_thumbs_down.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag nicht gefällt. +post_thumbs_down.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag nicht gefällt. Falls du diese Eingabe zurücknehmen willst, klicke einfach ein zweites Mal auf das Symbol.

        -post_share.png Mit diesem Symbol kannst du einen Beitrag weiter verteilen. -Einfach anklicken und sofort erscheint der Beitrag in deinem Beitragseditor. +post_share.png Mit diesem Symbol kannst du einen Beitrag weiter verteilen. +Einfach anklicken und sofort erscheint der Beitrag in deinem Beitragseditor. Am Ende des eingefügten Beitrags erscheint ein Link zum Originalbeitrag.

        -post_mark.png Mit diesem Symbol kannst du einen Beitrag für dich markieren. -Markierte Beiträge erscheinen in deiner Netzwerk-Seite unter "Markierte". +post_mark.png Mit diesem Symbol kannst du einen Beitrag für dich markieren. +Markierte Beiträge erscheinen in deiner Netzwerk-Seite unter "Markierte". Wenn du die Markierung entfernen willst, klicke einfach ein zweites Mal auf das Symbol.

        -post_tag.png Mit diesem Symbol kannst du einen tag zum Beitrag hinzufügen und diesen so einem bestimmten Schlagwort zuzuordnen. -Anschließend kannst du auf diesen tag klicken und alle Beiträge mit diesem tag ansehen. +post_tag.png Mit diesem Symbol kannst du einen tag zum Beitrag hinzufügen und diesen so einem bestimmten Schlagwort zuzuordnen. +Anschließend kannst du auf diesen tag klicken und alle Beiträge mit diesem tag ansehen. ACHTUNG: tags können nicht mehr entfernt werden.

        -post_categorize.png Mit diesem Symbol ist es möglich, die Beiträge in bestimmte Gruppen einzuordnen. -Dies dient dazu, gewählte Beiträge nach eigenen Vorstellungen zu sortieren und wieder zu finden. +post_categorize.png Mit diesem Symbol ist es möglich, die Beiträge in bestimmte Gruppen einzuordnen. +Dies dient dazu, gewählte Beiträge nach eigenen Vorstellungen zu sortieren und wieder zu finden. Wähle eine vorhandene Gruppe oder gib einen neuen Namen ein. Die erstellten Gruppen findest du unter "Gespeicherte Ordner" in der Netzwerk-Ansicht.

        post_delete.png Mit diesem Symbol löschst du deinen eigenen Beitrag bzw. entfernst einen Beitrag einer anderen Person aus deinem Stream.

        -post_choose.png Mit diesem Symbol kannst du mehrere Beiträge auswählen und gesammelt löschen. +post_choose.png Mit diesem Symbol kannst du mehrere Beiträge auswählen und gesammelt löschen. Hierfür gehst du nach dem Markieren aller gewünschten Beiträge auf "Lösche die markierten Beiträge" am Ende der Seite mit allen Beiträgen.

        diff --git a/doc/de/text-editor.md b/doc/de/text-editor.md index 062dd1f7f8..3b21f92c89 100644 --- a/doc/de/text-editor.md +++ b/doc/de/text-editor.md @@ -1,5 +1,4 @@ -Beiträge erstellen -================= +# Beiträge erstellen * [Zur Startseite der Hilfe](help) @@ -9,43 +8,43 @@ Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. -editor +editor Die einzelnen Symbole -editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. +editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. Wenn du eine Internetadresse (URL) eingeben willst, dann kannst du das "Baum"-Symbol im oberen Teil des Editors nutzen. Wenn du ein Bild ausgewählt hast, dann erscheint eine Miniaturdarstellung des Bildes im Editor.*

        -paper_clip Wenn du dieses Symbol anklickst, dann kannst du weitere Dateien von deinem Computer einfügen. Eine Vorschau des Dateiinhalts erfolgt nicht.* +paper_clip Wenn du dieses Symbol anklickst, dann kannst du weitere Dateien von deinem Computer einfügen. Eine Vorschau des Dateiinhalts erfolgt nicht.*

        -chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. +chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. Im Editor erscheint automatisch eine kurze Information zum eingefügten Link.*

        -video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. +video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. Das Video erscheint dann mit einem Player in deinem Beitrag. Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser verschiedene Videoformate unterstützt (z.B. WebM oder MP4). Außerdem kannst du hier die URLs von Videos auf Youtube, Vimeo und manchen anderen Videohostern eingeben. Die Videos werden dann mit Vorschaubild angezeigt, nach einem Klick öffnet sich ein eingebetteter Player.*

        -mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. +mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser und Betriebssystem MP3, Ogg oder AAC unterstützt. Außerdem kannst du hier auch URLs von manchen Audiohostern wie Soundcloud eingeben, um eine dort gespeicherte Audiodatei mit Player in deinem Beitrag anzuzeigen.*

        -globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. +globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. Hier reicht schon eine Angabe wie "Berlin" oder "10775". Dieser Eintrag führt anschließend zu einer Suchanfrage bei Google Maps.

        -* wie du Dateien hochladen kannst, erfährst du [hier](help/faq#upload) +* wie du Dateien hochladen kannst, erfährst du [hier](help/FAQ#upload) **Im Folgenden findest du Symbole weiterer Themen** -Frio frio.png +Frio frio.png -Vier vier.png +Vier vier.png diff --git a/doc/developer-domain-driven-design.md b/doc/developer-domain-driven-design.md index 8f3e58193a..843119e004 100644 --- a/doc/developer-domain-driven-design.md +++ b/doc/developer-domain-driven-design.md @@ -1,5 +1,4 @@ -Domain-Driven-Design -============== +# Domain-Driven-Design * [Home](help) * [Developer Intro](help/developers-intro) diff --git a/doc/developer-how-to-move-classes-to-src.md b/doc/developer-how-to-move-classes-to-src.md index 948ad5584d..bbb9c6dfa6 100644 --- a/doc/developer-how-to-move-classes-to-src.md +++ b/doc/developer-how-to-move-classes-to-src.md @@ -1,5 +1,4 @@ -How To Move Classes to `src` -============== +# How To Move Classes to `src` * [Home](help) * [Developer Intro](help/developers-intro) @@ -12,7 +11,7 @@ However, there are a significant number of items to check when moving a class fi ## Decide the namespace -This isn't the most technical decision of them all, but it has long lasting consequences as it will be the name that will be used to refer to this class from now on. +This isn't the most technical decision of them all, but it has long-lasting consequences as it will be the name that will be used to refer to this class from now on. There is [a shared Ethercalc sheet](https://ethercalc.org/friendica_classes) to suggest namespace/class names that lists all the already moved class files for inspiration. A few pointers though: @@ -34,7 +33,7 @@ namespace Friendica\Core; From now on, the `Config` class can be referred to as `Friendica\Core\Config`, however it isn't very practical, especially when the class was previously used as `Config`. Thankfully, PHP provides namespace shortcuts through `use`. -This language construct just provides a different naming scheme for a namespace or a class, but doesn't trigger the autoload mechanism on its own. +This language construct just provides a different naming scheme for a namespace or a class, but doesn't trigger the autoload-mechanism on its own. Here are the different ways you can use `use`: ````php diff --git a/doc/developers-intro.md b/doc/developers-intro.md index 3171f6c5c2..c4a1533a4c 100644 --- a/doc/developers-intro.md +++ b/doc/developers-intro.md @@ -6,7 +6,7 @@ Do you want to help us improve Friendica? Here we have compiled some hints on how to get started and some tasks to help you choose. -A project like Friendica is the sum of many different contributions. +A project like Friendica is the sum of many contributions. **Very different skills are required to make good software, not all of them involve coding!** We are looking for helpers in all areas, whether you write text or code, whether you spread the word to convince people or design new icons. Whether you feel like an expert or like a newbie - join us with your ideas! diff --git a/doc/events.md b/doc/events.md index 0ec2bc4608..bd9678eb3c 100644 --- a/doc/events.md +++ b/doc/events.md @@ -31,14 +31,14 @@ Fields marked with a *** have to be filled. * **Event Finishes**: enter the finishing date/time for the event here When you click in one of these fields a pop-up will be opened that allows you to pick the day and the time. -If you double clicked on the day box in the calendar these fields will be pre-filled for you. +If you double-clicked on the day box in the calendar these fields will be pre-filled for you. The finishing date/time has to be after the beginning date/time of the event. But you don't have to specify it. If the event is open-ended or the finishing date/time does not matter, just select the box below the two first fields. * **Title**: a title for the event * **Description**: a longer description for the event -* **Location**: the location the event will took place +* **Location**: the location the event will take place These three fields describe your events. In the description and location field you can use BBCode to format the text. diff --git a/doc/faq-admin.md b/doc/faq-admin.md index 8f6897c0ad..d4553bdf66 100644 --- a/doc/faq-admin.md +++ b/doc/faq-admin.md @@ -1,5 +1,4 @@ -Frequently Asked Questions (Admin) - FAQ -============== +# Frequently Asked Questions (Admin) - FAQ * [Home](help) @@ -11,12 +10,12 @@ Frequently Asked Questions (Admin) - FAQ -### Can I configure multiple domains with the same code instance? +## Can I configure multiple domains with the same code instance? No, this function is no longer supported as of Friendica 3.3 onwards. -### Where can I find the source code of friendica, addons and themes? +## Where can I find the source code of friendica, addons and themes? You can find the main repository [here](https://github.com/friendica/friendica). There you will always find the current stable version of friendica. @@ -26,12 +25,12 @@ Addons are listed at [this page](https://github.com/friendica/friendica-addons). If you are searching for new themes, you can find them at [github.com/bkil/friendica-themes](https://github.com/bkil/friendica-themes) -### I've changed my email address now the admin panel is gone? +## I've changed my email address now the admin panel is gone? Have a look into your config/local.config.php and fix your email address there. -### Can there be more then one admin for a node? +## Can there be more then one admin for a node? Yes. You just have to list more then one email address in the @@ -43,13 +42,14 @@ The listed emails need to be separated by a comma like this: ``` -### The Database structure seems not to be updated. What can I do? +## The Database structure seems not to be updated. What can I do? Please have a look at the Admin panel under [DB updates](/admin/dbsync/) and follow the link to *check database structure*. This will start a background process to check if the structure is up to the current definition. You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following command: - - bin/console dbstructure update +```sh +bin/console dbstructure update +``` if there occur any errors, please contact the [Friendica Support group](https://forum.friendi.ca/profile/helpers) or discuss in the [Friendica Admins group](https://forum.friendi.ca/profile/admins). diff --git a/doc/faq.md b/doc/faq.md index e269ee6caa..11bbf333ae 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -1,5 +1,4 @@ -Frequently Asked Questions - FAQ -============== +# Frequently Asked Questions - FAQ * [Home](help) @@ -16,8 +15,7 @@ Frequently Asked Questions - FAQ - -### Where I can find help? +## Where I can find help? If this FAQ does not answer your question you can always reach out to the community via the following options: @@ -34,7 +32,7 @@ If this FAQ does not answer your question you can always reach out to the commun ---> -### Why do I get warnings about SSL certificates? +## Why do I get warnings about SSL certificates? SSL (Secure Socket Layer) is a technology to encrypt data transfer between computers. Sometimes your browser warns you about a missing or invalid certificate. @@ -47,7 +45,7 @@ These warnings can have three reasons: We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/ssl).) -### How can I upload images, files, links, videos and sound files to posts? +## How can I upload images, files, links, videos and sound files to posts? You can upload images from your computer using the [editor](help/text-editor). An overview of all uploaded images is listed at *yourpage.com/profile/profilename/photos*. @@ -76,7 +74,7 @@ Some supported file types are WebM, MP4, MP3 and OGG. See Wikipedia for more of them ([video](http://en.wikipedia.org/wiki/HTML5_video), [audio](http://en.wikipedia.org/wiki/HTML5_audio)). -### Is it possible to have different avatars per profile? +## Is it possible to have different avatars per profile? Yes. On your Edit/Manage Profiles page, you will find a "change profile photo" link. @@ -84,7 +82,7 @@ Clicking this will take you to a page where you can upload a photograph and sele To avoid privacy leakage, we only display the photograph associated with your default profile as the avatar in your posts. -### How can I view Friendica in a certain language? +## How can I view Friendica in a certain language? You can do this by adding the `lang` parameter to the url in your url bar. The data in the parameter is a [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. @@ -101,12 +99,12 @@ in German: When a certain language is forced, the language remains until session is closed. -### How do blocked, ignored, archived and hidden contacts behave? +## How do blocked, ignored, archived and hidden contacts behave? These are various categories of contacts that are restricted in some way. Many of these types are related to [Safety](help/safety). -##### Blocked +### Blocked Direct communication will be blocked. Blocked contacts are not included in delivery, and their own posts to you are not imported. @@ -114,7 +112,7 @@ However, their conversations with your friends will still be visible in your str If you remove a contact completely, they can send you another friend request. Blocked contacts cannot do this. They cannot communicate with you directly, only through friends. -##### Ignored +### Ignored Ignored contacts are included in delivery and will receive your posts and private messages. However, we do not import their posts or private messages to you. @@ -122,18 +120,18 @@ Like blocking, you will still see this person's comments to posts made by your f An addon called "blockem" can be installed to collapse/hide all posts from a particular person in your stream if you desire complete blocking of an individual, including their conversations with your other friends. -##### Archived +### Archived Communication is not possible and will not be attempted. However, unlike blocking, existing posts this person made before being archived will be visible in your stream. -##### Hidden +### Hidden The contact not be displayed in your public friend list. However, a hidden contact will appear normally in conversations and this may expose their hidden status to anybody who can see the conversation. -### What happens when an account is removed? +## What happens when an account is removed? If you remove your account, it will be scheduled for permanent deletion in *seven days*. As soon as you activate the deletion process you won't be able to log in anymore. @@ -144,18 +142,18 @@ Your node will also issue removal requests to all your contacts; this will also Your username cannot be reissued for future sign-ups for security reasons. -### Can I follow a hashtag? +## Can I follow a hashtag? Yes. Simply add the hashtag to your saved searches. The posts will appear on your network page. For technical reasons, your answers to such posts won't appear on the "personal" tab in the network page and the whole thread isn't accessible via the API. -### How to create an RSS feed of the stream? +## How to create an RSS feed of the stream? If you want to share your public page via rss you can use one of the following links: -#### RSS feed of your posts +### RSS feed of your posts basic-url.com//feed/[nickname]/posts @@ -172,14 +170,15 @@ Example: Friendica Support https://forum.friendi.ca/feed/helpers/comments -### What friendica clients can I use? + +## What friendica clients can I use? Friendica supports [Mastodon API](help/api-mastodon) and [Twitter API | gnusocial](help/api). This means you can use some of the Mastodon and Twitter clients for Friendica. The available features are client specific and may differ. Clients dedicated to Friendica are marked in **bold**. -#### Android +### Android * [AndStatus](http://andstatus.org) ([F-Droid](https://f-droid.org/repository/browse/?fdid=org.andstatus.app), [Google Play](https://play.google.com/store/apps/details?id=org.andstatus.app)) * [Fedilab](https://fedilab.app) ([F-Droid](https://f-droid.org/app/fr.gouv.etalab.mastodon), [Google Play](https://play.google.com/store/apps/details?id=app.fedilab.android)) @@ -195,7 +194,7 @@ Clients dedicated to Friendica are marked in **bold**. * [TwidereX](https://github.com/TwidereProject/TwidereX-Android) ([F-Droid](https://f-droid.org/en/packages/com.twidere.twiderex/), [Google Play](https://play.google.com/store/apps/details?id=com.twidere.twiderex)) * [Yuito](https://github.com/accelforce/Yuito) ([Google Play](https://play.google.com/store/apps/details?id=net.accelf.yuito)) -#### iOS +### iOS * [Mastodon](https://joinmastodon.org/apps) ([App Store](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) * **[Relatica](https://gitlab.com/mysocialportal/relatica)** @@ -203,7 +202,7 @@ Clients dedicated to Friendica are marked in **bold**. * [Tooot](https://github.com/tooot-app) ([App Store](https://apps.apple.com/app/id1549772269)) * [TwidereX](https://github.com/TwidereProject/TwidereX-iOS) ([App Store](https://apps.apple.com/app/twidere-x/id1530314034)) -#### Linux +### Linux * [Choqok](https://choqok.kde.org) * **[Relatica](https://gitlab.com/mysocialportal/relatica)** @@ -211,19 +210,19 @@ Clients dedicated to Friendica are marked in **bold**. * [Toot](https://toot.readthedocs.io/en/latest/) * [Whalebird](https://whalebird.social/en/desktop/contents) ([GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### macOS +### macOS * **[Relatica](https://gitlab.com/mysocialportal/relatica)** * [TheDesk](https://thedesk.top/en/) ([GitHub](https://github.com/cutls/TheDesk)) * [Whalebird](https://whalebird.social/en/desktop/contents) ([App Store](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Windows +### Windows * **[Relatica](https://gitlab.com/mysocialportal/relatica)** * [TheDesk](https://thedesk.top/en/) ([GitHub](https://github.com/cutls/TheDesk)) * [Whalebird](https://whalebird.social/en/desktop/contents) ([Microsoft Store](https://apps.microsoft.com/detail/9nbw4csdv5hc), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Web Frontend +### Web Frontend * [Halcyon](https://www.halcyon.social/) * [Pinafore](https://github.com/nolanlawson/pinafore) diff --git a/doc/github.md b/doc/github.md index dc96bc420d..c9f4314726 100644 --- a/doc/github.md +++ b/doc/github.md @@ -1,12 +1,10 @@ -Friendica on GitHub -=================== +# Friendica on GitHub * [Home](help) Here is how you can work on the code with us. If you have any questions please write to the Friendica developers' group. -Introduction to the workflow with our GitHub repository -------------------------------------------------------- +## Introduction to the workflow with our GitHub repository 1. Install git on the system you will be developing on. 2. Create your own [GitHub](https://github.com) account. @@ -17,8 +15,7 @@ Follow the instructions provided here: [http://help.github.com/fork-a-repo/](htt 6. Commit your changes to your fork. Then go to your GitHub page and create a "Pull request" to notify us to merge your work. -Our Git Branches ----------------- +## Our Git Branches There are two relevant branches in the main repo on GitHub: @@ -26,8 +23,7 @@ There are two relevant branches in the main repo on GitHub: 2. develop: This branch contains the latest code. This is what you want to work with. -Fast-forwarding ---------------- +## Fast-forwarding Fast forwarding is enabled by default in git. When you merge with fast-forwarding it does not add a new commit to mark when you've performed the merge and how. @@ -37,8 +33,7 @@ This is done by running "git merge --no-ff". [Here](https://stackoverflow.com/questions/5519007/how-do-i-make-git-merges-default-be-no-ff-no-commit) is an explanation on how to configure git to turn off fast-forwarding by default. You can find some more background reading [here](http://nvie.com/posts/a-successful-git-branching-model/). -Release branches ----------------- +## Release branches A release branch is created when the develop branch contains all features it should have. A release branch is used for a few things. @@ -55,8 +50,7 @@ If you were to merge develop into release-3.4 at this point, features and bug-fi This might introduce new bugs, too. Which defeats the purpose of the release branch. -Some important reminders ------------------------- +## Some important reminders 1. Please pull in any changes from the project repository and merge them with your work **before** issuing a pull request. We reserve the right to reject any patch which results in a large number of merge conflicts. @@ -69,8 +63,9 @@ Don't hesitate to ask us in case of doubt. 3. Check your code for typos. There is a console command called *typo* for this. - - $> php bin/console.php typo +```sh +php bin/console.php typo +``` Check out how to work with [our Vagrant](help/vagrant) to save a lot of setup time! diff --git a/doc/groups.md b/doc/groups.md index 3c2e17929d..634223263c 100644 --- a/doc/groups.md +++ b/doc/groups.md @@ -1,23 +1,20 @@ -Groups -===== +# Groups * [Home](help) - Friendica also lets you create accounts that can function as discussion groups, celebrity accounts, announcement channels, news reflectors, or organization pages, depending on how you want to interact with others. Management of these accounts can be delegated to other accounts, or a parent account can be designated to easily toggle multiple identities. Every account in Friendica has a nickname and these must all be unique. This applies to all accounts, whether they are individual profiles or group profiles. -Managing Accounts ---- +## Managing Accounts To create a new linked account that can be used as a group, log in to your normal account and go to Settings > Manage Accounts. Here you can register additional accounts with new nicknames that will be linked to your primary account. You may appoint a delegate to manage your new account. -The Delegates section of Manage Accounts page will provide you with a list of contacts on this instance under "Potential Delegates". +The "Delegates" section of Manage Accounts page will provide you with a list of contacts on this instance under "Potential Delegates". Selecting one or more persons will give them access to manage your newly created account. They will be able to edit contacts, profiles, and all content for this account. Please use this facility wisely. @@ -26,8 +23,7 @@ Delegated managers will not be able to alter basic account settings, such as pas Additionally, this page is also where you can choose to designate an account as a parent user. If your primary account is designated as the parent user, you will be able to easily toggle identities and manage your groups or other types of accounts. -Types of Accounts ---- +## Types of Accounts On the new account, visit the Settings > Account page. Towards the end of the page is a section for "Advanced account types". @@ -47,8 +43,7 @@ Organization and New Pages automatically approve contact requests as followers. Community Group provide the ability for people to join the group without requiring approval. This creates a group where all members can freely interact. -Posting to Community groups ---- +## Posting to Community groups If you are a member of a community group, you may post to the group by including an @-mention in the post mentioning the group. For example @bicycle would send my post to all members of the group "bicycle" in addition to the normal recipients. diff --git a/doc/home.md b/doc/home.md index ead9d66d37..256f14b187 100644 --- a/doc/home.md +++ b/doc/home.md @@ -1,11 +1,10 @@ -Help -==== +# Help -**User Manual** +## User Manual * General functions - first steps * [Account Basics](help/account-basics) - * [New User Quick Start](help/quick-qtart-guide) + * [New User Quick Start](help/quick-start/guide) * [Creating posts](help/text-editor) * [BBCode tag reference](help/bbcode) * [Comment, sort and delete posts](help/text-comment) @@ -26,7 +25,7 @@ Help * [Delete your account](help/remove-account) * [Frequently asked questions (FAQ)](help/faq) -**Admin Manual** +## Admin Manual * [Install](help/install) * [Update](help/update) @@ -40,7 +39,7 @@ Help * [Administration Tools](help/tools) * [Admin FAQ](help/faq-admin) -**Developer Manual** +## Developer Manual * [Get started](help/developers-intro) * Set up development environment @@ -65,7 +64,7 @@ Help * [Database schema documentation](help/database) * [Class Autoloading](help/autoloader) -**Links** +## Links * Website: [https://friendi.ca](https://friendi.ca) * Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) @@ -73,9 +72,7 @@ Help * IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) * Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) * Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) - - -**About** +## About * [Server Information](friendica) * [Terms of Service](tos) diff --git a/doc/improve-performance.md b/doc/improve-performance.md index 9134cb6c74..8c8b870c5f 100644 --- a/doc/improve-performance.md +++ b/doc/improve-performance.md @@ -1,25 +1,22 @@ -How to improve the performance of a Friendica site -============== +# How to improve the performance of a Friendica site * [Home](help) Feel free to ask in the [Friendica support group](https://forum.friendi.ca/profile/helpers) if you need some clarification about the following instructions or if you need help in any other way. -System configuration --------- +## System configuration -Please go to /admin/site/ on your system and change the following values: +Please go to `/admin/site/` on your system and change the following values: Set "JPEG image quality" to 50. -This value reduces the data that is send from the server to the client. 50 is a value that doesn't influences image quality too much. +This value reduces the data that is sent from the server to the client. 50 is a value that doesn't influence image quality too much. Enable "Use MySQL full text engine" When using MyISAM (default) or InnoDB on MariaDB 10 this speeds up search. -Addons --------- +## Addons Active the following addons: @@ -43,8 +40,7 @@ They show your performance problems. Others: Everything else :) Total: The sum of all above values -Apache Webserver --------- +## Apache Webserver The following Apache modules are recommended: @@ -53,20 +49,20 @@ The following Apache modules are recommended: This module tells the client to cache the content of static files so that they aren't fetched with every request. Enable the module "mod_expires" by typing in "a2enmod expires" as root. Please add the following lines to your site configuration in the "directory" context. - - ExpiresActive on ExpiresDefault "access plus 1 week" +``` +ExpiresActive on ExpiresDefault "access plus 1 week" +``` Also see the Apache [2.2](http://httpd.apache.org/docs/2.2/mod/mod_expires.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_expires.html) documentation. ### Compress content This module compresses the traffic between the web server and the client. -Enable the module "mod_deflate" by typing in "a2enmod deflate" as root. +Enable the module `mod_deflate` by typing in `a2enmod deflate` as root. -Also see the Apache [2.2](http://httpd.apache.org/docs/2.2/mod/mod_deflate.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_deflate.html) documentation. +Also see the Apache [2.2](https://httpd.apache.org/docs/2.2/mod/mod_deflate.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_deflate.html) documentation. -PHP --------- +## PHP ### FCGI diff --git a/doc/install-ejabberd.md b/doc/install-ejabberd.md index dbdc0b975d..6137540286 100644 --- a/doc/install-ejabberd.md +++ b/doc/install-ejabberd.md @@ -1,45 +1,49 @@ -Install an ejabberd with synchronized credentials -================================================= +# Install an ejabberd with synchronized credentials * [Home](help) [Ejabberd](https://www.ejabberd.im/) is a chat server that uses XMPP as messaging protocol that you can use with a large amount of clients. In conjunction with the "xmpp" addon it can be used for a web based chat solution for your users. -Installation ------------- +## Installation -- Change it's owner to whichever user is running the server, ie. ejabberd +- Change its owner to whichever user is running the server, ie. ejabberd +```sh +chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php +``` - $ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php - -- Change the access mode so it is readable only to the user ejabberd and has exec - - $ chmod 700 /path/to/friendica/bin/auth_ejabberd.php +- Change the access mode, so it is readable only to the user ejabberd and has exec +```sh +chmod 700 /path/to/friendica/bin/auth_ejabberd.php +``` - Edit your ejabberd.cfg file, comment out your auth_method and add: - - {auth_method, external}. - {extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}. +``` +{auth_method, external}. +{extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}. +``` - Disable the module "mod_register" and disable the registration: - - {access, register, [{deny, all}]}. +``` +{access, register, [{deny, all}]}. +``` - Enable BOSH: - Enable the module "mod_http_bind" - Edit this line: - - {5280, ejabberd_http, [captcha, http_poll, http_bind]} +``` +{5280, ejabberd_http, [captcha, http_poll, http_bind]} +``` - In your apache configuration for your site add this line: +``` +ProxyPass /http-bind http://127.0.0.1:5280/http-bind retry=0 +``` - ProxyPass /http-bind http://127.0.0.1:5280/http-bind retry=0 +- Restart your ejabberd service, you should be able to log in with your friendica credentials -- Restart your ejabberd service, you should be able to login with your friendica credentials +## Other hints -Other hints ------------ - if a user has a space or a @ in the nickname, the user has to replace these characters: - " " (space) is replaced with "%20" - "@" is replaced with "(a)" diff --git a/doc/install.md b/doc/install.md index 54332a674b..ae454ef75c 100644 --- a/doc/install.md +++ b/doc/install.md @@ -1,7 +1,7 @@ # Friendica Installation -We've tried very hard to ensure that Friendica will run on commodity hosting platforms - such as those used to host Wordpress blogs and Drupal websites. +We've tried very hard to ensure that Friendica will run on commodity hosting platforms - such as those used to host WordPress blogs and Drupal websites. We offer a manual and an automatic installation. But be aware that Friendica is more than a simple web application. @@ -15,7 +15,7 @@ Many will. But **please** review the requirements below and confirm these with your hosting provider prior to installation. ## Support -If you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). +If you encounter installation issues, please let us know via the [helper](https://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). Please be as clear as you can about your operating environment and provide as much detail as possible about any error messages you may see, so that we can prevent it from happening in the future. Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues. @@ -27,7 +27,7 @@ Due to the large variety of operating systems and PHP platforms in existence we ### Requirements -* Apache with mod_rewrite enabled and "[AllowOverride All](https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)" so you can use a local `.htaccess` file +* Apache with `mod_rewrite` enabled and "[AllowOverride All](https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)" so you can use a local `.htaccess` file * PHP 7.4+ * PHP *command line* access with register_argc_argv set to true in the php.ini file * Curl, GD, GMP, PDO, mbstring, MySQLi, xml, zip, IntlChar, IDN and OpenSSL extensions @@ -74,33 +74,40 @@ Clone the [friendica/friendica GitHub repository](https://github.com/friendica/f This makes the software much easier to update. The Linux commands to clone the repository into a directory "mywebsite" would be - - git clone https://github.com/friendica/friendica.git -b stable mywebsite +```sh +git clone https://github.com/friendica/friendica.git -b stable mywebsite +``` Get the addons by going into your website folder. - - cd mywebsite +```sh +cd mywebsite +``` Clone the addon repository (separately): - - git clone https://github.com/friendica/friendica-addons.git -b stable addon +```sh +git clone https://github.com/friendica/friendica-addons.git -b stable addon +``` Install the dependencies: - - bin/composer.phar run install:prod +```sh +bin/composer.phar run install:prod +``` Make sure the folder *view/smarty3* exists and is writable by the webserver user, in this case *www-data* - - mkdir -p view/smarty3 - chown www-data:www-data view/smarty3 - chmod 775 view/smarty3 +```sh +mkdir -p view/smarty3 +chown www-data:www-data view/smarty3 +chmod 775 view/smarty3 +``` If you want to use the development version of Friendica you can switch to the develop branch in the repository by running - git checkout develop - bin/composer.phar run install:prod - cd addon - git checkout develop +```sh +git checkout develop +bin/composer.phar run install:prod +cd addon +git checkout develop +``` **Be aware that the develop branch is unstable and may break your Friendica node at any time.** You should have a recent backup before updating. @@ -111,15 +118,19 @@ If you encounter a bug, please let us know. Create an empty database and note the access details (hostname, username, password, database name). Generate a strong password, then enter mysql with: - mysql +```sh +mysql +``` Then use the following script using the password you just generated: - CREATE DATABASE friendicadb; - CREATE USER 'friendica'@'localhost' IDENTIFIED BY '<>'; - GRANT ALL ON friendicadb.* TO 'friendica'@'localhost'; - FLUSH PRIVILEGES; - EXIT; +```sql +CREATE DATABASE friendicadb; +CREATE USER 'friendica'@'localhost' IDENTIFIED BY '<>'; +GRANT ALL ON friendicadb.* TO 'friendica'@'localhost'; +FLUSH PRIVILEGES; +EXIT; +``` Friendica needs the permission to create and delete fields and tables in its own database. @@ -144,42 +155,45 @@ Registration errors should all be recoverable automatically. If you get any *critical* failure at this point, it generally indicates the database was not installed correctly. You might wish to move/rename `config/local.config.php` to another name and empty (called 'dropping') the database tables, so that you can start fresh. -### Option B: Run the automatic install script +### Option B: Run the automatic installation script You have the following options to automatically install Friendica: -- creating a prepared config file (f.e. `prepared.config.php`) -- using environment variables (f.e. `MYSQL_HOST`) -- using options (f.e. `--dbhost `) +- creating a prepared config file (f.e. `prepared.config.php`) +- using environment variables (f.e. `MYSQL_HOST`) +- using options (f.e. `--dbhost `) You can combine environment variables and options, but be aware that options are prioritized over environment variables. For more information during the installation, you can use this command line option - - bin/console autoinstall -v +```sh +bin/console autoinstall -v +``` If you wish to include all optional checks, use `-a` like this statement: - - bin/console autoinstall -a +```sh +bin/console autoinstall -a +``` *If* the automatic installation fails for any reason, check the following: -* Does `config/local.config.php` already exist? If yes, the automatic installation won't start -* Are the options in the `config/local.config.php` correct? If not, edit them directly. -* Is the empty MySQL-database created? If not, create it. +* Does `config/local.config.php` already exist? If yes, the automatic installation won't start +* Are the options in the `config/local.config.php` correct? If not, edit them directly. +* Is the empty MySQL-database created? If not, create it. #### B.1: Config file You can use a prepared config file like [local-sample.config.php](/config/local-sample.config.php). Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall -f +```sh +bin/console autoinstall -f +``` #### B.2: Environment variables There are two types of environment variables. -- those you can use in normal mode too (Currently just **database credentials**) -- those you can only use during installation (because Friendica will normally ignore it) +- those you can use in normal mode too (Currently just **database credentials**) +- those you can only use during installation (because Friendica will normally ignore it) You can use the options during installation too and skip some of the environment variables. @@ -187,53 +201,56 @@ You can use the options during installation too and skip some of the environment if you don't use the option `--savedb` during installation, the DB credentials will **not** be saved in the `config/local.config.php`. -- `MYSQL_HOST` The host of the mysql/mariadb database -- `MYSQL_PORT` The port of the mysql/mariadb database -- `MYSQL_USERNAME` The username of the mysql database login (used for mysql) -- `MYSQL_USER` The username of the mysql database login (used for mariadb) -- `MYSQL_PASSWORD` The password of the mysql/mariadb database login -- `MYSQL_DATABASE` The name of the mysql/mariadb database +- `MYSQL_HOST` The host of the mysql/mariadb database +- `MYSQL_PORT` The port of the mysql/mariadb database +- `MYSQL_USERNAME` The username of the mysql database login (used for mysql) +- `MYSQL_USER` The username of the mysql database login (used for mariadb) +- `MYSQL_PASSWORD` The password of the mysql/mariadb database login +- `MYSQL_DATABASE` The name of the mysql/mariadb database **Friendica settings** -This variables wont be used at normal Friendica runtime. +These variables won't be used at normal Friendica runtime. Instead, they get saved into `config/local.config.php`. -- `FRIENDICA_URL_PATH` The URL path of Friendica (f.e. '/friendica') -- `FRIENDICA_PHP_PATH` The path of the PHP binary -- `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access) -- `FRIENDICA_TZ` The timezone of Friendica -- `FRIENDICA_LANG` The language of Friendica +- `FRIENDICA_URL_PATH` The URL path of Friendica (f.e. '/friendica') +- `FRIENDICA_PHP_PATH` The path of the PHP binary +- `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access) +- `FRIENDICA_TZ` The timezone of Friendica +- `FRIENDICA_LANG` The language of Friendica Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall [--savedb] +```sh +bin/console autoinstall [--savedb] +``` #### B.3: Execution options All options will be saved in the `config/local.config.php` and are overruling the associated environment variables. -- `-H|--dbhost ` The host of the mysql/mariadb database (env `MYSQL_HOST`) -- `-p|--dbport ` The port of the mysql/mariadb database (env `MYSQL_PORT`) -- `-U|--dbuser ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) -- `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) -- `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) -- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) -- `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) -- `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) -- `-L|--lang ` The language of Friendica (env `FRIENDICA_LANG`) +- `-H|--dbhost ` The host of the mysql/mariadb database (env `MYSQL_HOST`) +- `-p|--dbport ` The port of the mysql/mariadb database (env `MYSQL_PORT`) +- `-U|--dbuser ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) +- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) +- `-L|--lang ` The language of Friendica (env `FRIENDICA_LANG`) Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall [options] +```sh +bin/console autoinstall [options] +``` ### Prepare .htaccess file Copy `.htaccess-dist` to `.htaccess` (be careful under Windows) to have working mod-rewrite again. If you have installed Friendica into a sub directory, like */friendica/* set this path in `RewriteBase` accordingly. Example: - - cp .htaccess-dist .htaccess +```sh +cp .htaccess-dist .htaccess +``` *Note*: Do **not** rename the `.htaccess-dist` file as it is tracked by GIT and renaming will cause a dirty working directory. @@ -250,9 +267,9 @@ Another common error related to host-meta is the "Invalid profile URL." Check for a `.well-known` directory that did not come with Friendica. The preferred configuration is to remove the directory, however this is not always possible. -If there is any /.well-known/.htaccess file, it could interfere with this Friendica core requirement. -You should remove any RewriteRules from that file, or remove that whole file if appropriate. -It may be necessary to chmod the /.well-known/.htaccess file if you were not given write permissions by default. +If there is any `/.well-known/.htaccess` file, it could interfere with this Friendica core requirement. +You should remove any `RewriteRules` from that file, or remove that whole file if appropriate. +It may be necessary to `chmod` the `/.well-known/.htaccess` file if you were not given write permissions by default. ## Register the admin account @@ -268,8 +285,9 @@ You might wish to delete/rename `config/local.config.php` to another name and dr Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing. Example: - - cd /base/directory; /path/to/php bin/console.php worker +```sh +cd /base/directory; /path/to/php bin/console.php worker +``` Change "/base/directory", and "/path/to/php" as appropriate for your situation. @@ -277,8 +295,9 @@ Change "/base/directory", and "/path/to/php" as appropriate for your situation. If you are using a Linux server, run "crontab -e" and add a line like the one shown, substituting for your unique paths and settings: - - */10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +```crontab +*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +``` You can generally find the location of PHP by executing "which php". If you run into trouble with this section please contact your hosting provider for assistance. @@ -290,12 +309,15 @@ Once you have installed Friendica and created an admin account as part of the pr #### worker alternative: daemon Otherwise, you’ll need to use the command line on your remote server and start the Friendica daemon (background task) using the following command: - - cd /path/to/friendica; php bin/console.php daemon start +```sh +cd /path/to/friendica; php bin/console.php daemon start +``` Once started, you can check the daemon status using the following command: - cd /path/to/friendica; php bin/console.php daemon status +```sh +cd /path/to/friendica; php bin/console.php daemon status +``` After a server restart or any other failure, the daemon needs to be restarted. This could be achieved by a cronjob. @@ -319,16 +341,23 @@ As it stores all your data, you should also have a recent dump of your Friendica Friendica looks for some well-known HTTP headers indicating a reverse-proxy terminating an HTTPS connection. While the standard from RFC 7239 specifies the use of the `Forwarded` header. - - Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2 +``` +Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2 +``` Friendica also supports a number on non-standard headers in common use. - X-Forwarded-Proto: https +``` +X-Forwarded-Proto: https +``` - Front-End-Https: on +``` +Front-End-Https: on +``` - X-Forwarded-Ssl: on +``` +X-Forwarded-Ssl: on +``` It is however preferable to use the standard approach if configuring a new server. @@ -355,12 +384,12 @@ Often this will need to be resolved with your hosting provider or (if self-hoste First check your file permissions. Your website and all contents must generally be world-readable. -Ensure that mod-rewrite is installed and working, and that your `.htaccess` file +Ensure that `mod-rewrite` is installed and working, and that your `.htaccess` file is being used. To verify the latter, create a file `test.out` containing the word "test" in the top directory of Friendica, make it world readable and point your web browser to - http://yoursitenamehere.com/test.out +> http://yoursitenamehere.com/test.out This file should be blocked. You should get a permission denied message. @@ -376,9 +405,10 @@ If you do not see the word "test", your `.htaccess` is working, but it is likely that mod-rewrite is not installed in your web server or is not working. On most Linux flavors: - - % a2enmod rewrite - % /etc/init.d/apache2 restart +```sh +a2enmod rewrite +/etc/init.d/apache2 restart +``` Consult your hosting provider, experts on your particular Linux distribution or (if Windows) the provider of your Apache server software if you need to change @@ -391,15 +421,17 @@ distribution or Apache package (if using Windows). Create an empty `config/local.config.php`file and apply world-write permission. On Linux: - - % touch config/local.config.php - % chmod 664 config/local.config.php +```sh +touch config/local.config.php +chmod 664 config/local.config.php +``` Retry the installation. As soon as the database has been created, ******* this is important ********* - - % chmod 644 config/local.config.php +```sh +chmod 644 config/local.config.php +``` ### Suhosin issues @@ -436,7 +468,7 @@ provided by one of our members. > (attacker 'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php', > line 1341) > -> After a while I noticed, that `bin/console.php worker` calls further PHP script via `proc_open`. +> After a while I noticed, that `bin/console.php worker` calls further PHP scripts via `proc_open`. > These scripts themselves also use `proc_open` and fail, because they are NOT > called with `-d suhosin.executor.func.blacklist=none`. > @@ -457,12 +489,13 @@ provided by one of our members. If the setup fails to create all the database tables and/or manual creation from the command line fails, with this error: - ERROR 1067 (42000) at line XX: Invalid default value for 'created' +> ERROR 1067 (42000) at line XX: Invalid default value for 'created' You need to adjust your my.cnf and add the following setting under the [mysqld] section: - - sql_mode = ''; +``` +sql_mode = ''; +``` After that, restart mysql and try again. @@ -549,9 +582,11 @@ You may also set it manually in the config file or in the database within the `d Altering of a table may fail if it contains a large number of rows. First verify the existing timeout (50s by default): - -`show global variables like "innodb_lock_wait_timeout";` +```sql +show global variables like "innodb_lock_wait_timeout"; +``` Then increase it: - -`set global innodb_lock_wait_timeout=600;` +```sql +set global innodb_lock_wait_timeout=600; +``` diff --git a/doc/installing-connectors.md b/doc/installing-connectors.md index bd564eb466..9f88aa3c6c 100644 --- a/doc/installing-connectors.md +++ b/doc/installing-connectors.md @@ -1,5 +1,4 @@ -Installing Connectors -================================================== +# Installing Connectors * [Home](help) @@ -8,8 +7,7 @@ Friendica uses add-ons to connect to some networks, such as Tumblr or Bluesky. All of these add-ons require an account on the target network. In addition, you (or usually the server administrator) will need to obtain an API key to allow authenticated access to your Friendica server. -Site configuration ---- +## Site configuration Addons need to be installed by the site administrator before they can be used. This is done through the site administration panel. @@ -20,8 +18,7 @@ Other connectors, such as Bluesky, don't require an API key at all. You can find more information about specific requirements on each addon's settings page, either on the admin page or the user page. -Bluesky Jetstream ---- +## Bluesky Jetstream To further improve connectivity to Bluesky, Admins can choose to enable 'Jetstream' connectivity. Jetstream is a service that connects to the Bluesky firehose. diff --git a/doc/keyboard-shortcuts.md b/doc/keyboard-shortcuts.md index cf783b0da1..8e27168e54 100644 --- a/doc/keyboard-shortcuts.md +++ b/doc/keyboard-shortcuts.md @@ -1,10 +1,8 @@ -Keyboard shortcuts in Friendica -======================= +# Keyboard shortcuts in Friendica * [Home](help) -General -------- +## General * j: Scroll to next thread * k: Scroll to previous thread diff --git a/doc/making-friends.md b/doc/making-friends.md index eb5109880a..fda844c5d6 100644 --- a/doc/making-friends.md +++ b/doc/making-friends.md @@ -1,5 +1,4 @@ -Making Friends -============== +# Making Friends * [Home](help) @@ -7,8 +6,8 @@ Friendship in Friendica can sometimes take on different meaning. But let's keep it simple; you want to be friends with somebody. How do you do it? -The Directories ---- +## The Directories + Friendica has two different kinds of "address book". The directory of the Friendica server you are registered on and a global directory to which your and other Friendica servers submit account information. @@ -23,8 +22,7 @@ If you click through to the global directory, you will be presented with a list You will also see a "Show Community Groups" link, which will direct you to Groups. You connect to people and groups the same way, public groups will automatically accept your introduction, whereas private groups and some individual users will need to manually approve it. -Connect to other Friendica users ---- +## Connect to other Friendica users Visit their profile. Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile). @@ -48,8 +46,8 @@ If you already know somebody's Identity Address, you can enter it in the "connec This will take you through a similar process. -Connect to users of alternate networks ---- +## Connect to users of alternate networks + ### Across the Federation and Fediverse You can also use your Identity Address or other people's Identity Addresses to become friends across the so-called Federation/Fediverse of open source social media. Currently, Friendica supports connections with people on diaspora*, Red, Hubzilla, GNU Social, StatusNet, Mastodon, Pleroma, socialhome, and ganggo platforms. @@ -80,31 +78,29 @@ To subscribe to a mailing list, enter the email in following example format "mai You can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.). If we can find an information stream and a name to attach to the contact, we'll try to connect with them. -Notification ---- +## Notification + When somebody requests friendship you will receive a notification. You will usually need to approve this before the friendship is complete. -Approval ---- +## Approval + Some networks allow people to send you messages without being friends and without your approval. Friendica does not allow this by default, as it would open a gateway for spam. -Unilateral or bilateral friendships ---- +## Unilateral or bilateral friendships + When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "Follower" or as a "Friend". If they are a follower, they can see what you have to say, including private communications that you send to them, but not vice versa. As a friend, you can both communicate with each other. diaspora* uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends. -Deleting ---- +## Deleting You can delete a friend no matter what the friendship status - which completely removes everything relating to that person from your website. -Unwanted Behaviour ---- +## Unwanted Behaviour If a contact engages in abuse, harrassment, or other unwanted behaviour, there are various actions you can take. These include: diff --git a/doc/message-flow.md b/doc/message-flow.md index e967985695..4723026cee 100644 --- a/doc/message-flow.md +++ b/doc/message-flow.md @@ -1,5 +1,4 @@ -Friendica Message Flow -=== +# Friendica Message Flow This page documents some of the details of how messages get from one person to another in the Friendica network. There are multiple paths, using multiple protocols and message formats. @@ -11,7 +10,7 @@ This file also invokes the local side of all deliveries including DFRN-notify. mod/dfrn_notify.php handles the remote side of DFRN-notify. -Local feeds are generated by mod/dfrn_poll.php - which also handles the remote side of DFRN-poll protocol. +Local feeds are generated by mod/dfrn_poll.php - which also handles the remote side of DFRN-poll protocol. Salmon notifications arrive via mod/salmon.php. @@ -19,7 +18,7 @@ Push (pubsubhubbub) feeds arrive via mod/pubsub.php DFRN-poll feed imports arrive via src/Worker/OnePoll.php as a scheduled task, this implements the local side of the DFRN-poll protocol. -### Scenario #1. Bob posts a public status message +## Scenario #1. Bob posts a public status message This is a public message with no conversation members so no private transport is used. There are two paths it can take - as a bbcode path to DFRN clients, and converted to HTML with the server's PuSH (pubsubhubbub) hubs notified. @@ -28,30 +27,30 @@ They will fall back on a daily poll in case the hub has delivery issues (this is If there is no specified hub or hubs, DFRN clients will poll at a configurable (per-contact) rate at up to 5-minute intervals. Feeds retrieved via dfrn-poll are bbcode and may also contain private conversations which the worker has permissions to see. -### Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network. +## Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network. Jack uses dfrn-notify to send a direct reply to Bob. Bob then creates a feed of the conversation and sends it to everybody involved in the conversation using dfrn-notify. PuSH hubs are notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network. +## Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network. Mary uses dfrn-notify to send a direct reply to Bob. Bob then creates a feed of the conversation and sends it to everybody involved in the conversation (excluding himself, the conversation is now sent to both Jack and Mary). Messages are sent using dfrn-notify. Push hubs are also notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #4. William replies to Bob's public message. William is on the OStatus network. +## Scenario #4. William replies to Bob's public message. William is on the OStatus network. William uses salmon to notify Bob of the reply. Content is html embedded in salmon magic envelope. Bob then creates a feed of the conversation and sends it to all Friendica participants involved in the conversation using dfrn-notify (excluding himself, the conversation is sent to both Jack and Mary). Push hubs are notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #5. Bob posts a private message to Mary and Jack. +## Scenario #5. Bob posts a private message to Mary and Jack. Message is delivered immediately to Mary and Jack using dfrn_notify. Public hubs are not notified. diff --git a/doc/migrate.md b/doc/migrate.md index ca0e0d0d95..42db707c81 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,5 +1,4 @@ -Migrating to a new server installation -=============== +# Migrating to a new server installation * [Home](help) @@ -39,9 +38,9 @@ Before transferring your database, you may want to clean it up; ensure the expir After adjusting these settings, the database cleaning up processes will be initiated according to your configured daily cron job. To review the size of your database, log into MySQL with ``mysql -p`` run the following query: -```` +```sql SELECT table_schema AS "Database", SUM(data_length + index_length) / 1024 / 1024 / 1024 AS "Size (GB)" FROM information_schema.TABLES GROUP BY table_schema; -```` +``` You should see an output like this: ```` @@ -89,4 +88,3 @@ If you are unable to login to your newly migrated Friendica installation, check If still unable to resolve the problem, it's likely an issue with your [installation](Install). In this case, you may try to an entirely new Friendica installation on your new server, but use a different FQDN and DNS name. Once you have this up and running, take it offline and purge the database and configuration file and try migrating to this installation. - diff --git a/doc/move-account.md b/doc/move-account.md index 9e13d7cad8..5814410da6 100644 --- a/doc/move-account.md +++ b/doc/move-account.md @@ -1,5 +1,4 @@ -How to move your account between servers -============ +# How to move your account between servers * [Home](help) @@ -14,13 +13,12 @@ How to move your account between servers * Load your saved account file and click "Import". * After the move, the account on the old server will not work reliably anymore, and should be not used. +## Friendica contacts -Friendica contacts ---- Friendica will recreate your account on the new server, with your contacts and circles. A message is sent to Friendica contacts, to inform them about your move: If your contacts are running on an updated server, your details on their side will be automatically updated. -Diaspora contacts ---- +## Diaspora contacts + Newer Diaspora servers are able to process "account migration" messages. diff --git a/doc/protocol.md b/doc/protocol.md index 25e9cebdf9..2580c0f9fd 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -1,18 +1,16 @@ -Used Protocols -=============== +# Used Protocols * [Home](help) -Friendicas DFRN Protocol ---- +## Friendicas DFRN Protocol * [Document with the DFRN specification](spec/dfrn2.pdf) * [Schema of the contact request process](spec/dfrn2_contact_request.png) * [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png) * [Description of the message flow](help/message-flow) -ActivityStreams ---- +## ActivityStreams + Friendica is using ActivityStreams in version 1.0 for its activities and object types. Additional types are used for non standard activities. @@ -20,8 +18,7 @@ Additional types are used for non standard activities. * [Link to the specification](http://activitystrea.ms/head/activity-schema.html) * [List of used ActivityStreams verbs and object types.](https://github.com/friendica/friendica/wiki/ActivityStreams) -Portable Contacts ---- +## Portable Contacts Portable Contacts is used for friends lists. diff --git a/doc/quick-start-finally.md b/doc/quick-start-finally.md deleted file mode 100644 index 7ea3f5dc72..0000000000 --- a/doc/quick-start-finally.md +++ /dev/null @@ -1,14 +0,0 @@ -And that brings the Quick Start to an end. - -Here are some more things to help get you started: - -**Groups** - -- Friendica Support - problems? This is the place to ask. - -**Documentation** - -- Connecting to more networks -- Help Index - - diff --git a/doc/quick-start/finally.md b/doc/quick-start/finally.md new file mode 100644 index 0000000000..b04fe4ad1d --- /dev/null +++ b/doc/quick-start/finally.md @@ -0,0 +1,12 @@ +And that brings the Quick Start to an end. + +Here are some more things to help get you started: + +**Groups** + +- [Friendica Support](https://forum.friendi.ca/profile/helpers) - problems? This is the place to ask. + +**Documentation** + +- [Connections to other networks](help/connectors) +- [Help index](help) diff --git a/doc/quick-start-groups-and-pages.md b/doc/quick-start/groups-and-pages.md similarity index 81% rename from doc/quick-start-groups-and-pages.md rename to doc/quick-start/groups-and-pages.md index 0fd27b5338..d9c5bb6893 100644 --- a/doc/quick-start-groups-and-pages.md +++ b/doc/quick-start/groups-and-pages.md @@ -1,5 +1,5 @@ This is the global directory. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/quick-start/groups-and-pages) to bring yourself back here. On this page, you'll find a collection of groups. Groups are not real people. @@ -13,8 +13,6 @@ Simply find a group you're interested in, and connect to it the same way you did There are a lot of groups, and you're likely to get lost. Remember the link at the top of this page will bring you back here. -Once you've added some groups, move on to the next section. +Once you've added some groups, [move on to the next section](help/quick-start/finally). - - diff --git a/doc/quick-start-guide.md b/doc/quick-start/guide.md similarity index 95% rename from doc/quick-start-guide.md rename to doc/quick-start/guide.md index b31684dda2..baa9b992a1 100644 --- a/doc/quick-start-guide.md +++ b/doc/quick-start/guide.md @@ -18,8 +18,6 @@ Once you've finished writing your post, click on the padlock icon or permissions If you do not change anything, your post will be public. This means it will appear to anybody who views your profile, and in the community tab if your site has it enabled, as well as in the network tab of any of your contacts. -Play around with this a bit, then when you're ready to move on, we'll take a look at the Network Tab +Play around with this a bit, then when you're ready to move on, we'll take a look at the [Network Tab](help/quick-start/network). - - diff --git a/doc/quick-start-making-new-friends.md b/doc/quick-start/making-new-friends.md similarity index 79% rename from doc/quick-start-making-new-friends.md rename to doc/quick-start/making-new-friends.md index 4971d3dd1d..b81f18c46c 100644 --- a/doc/quick-start-making-new-friends.md +++ b/doc/quick-start/making-new-friends.md @@ -1,5 +1,5 @@ This is your Suggested Friends page. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/quick-start/making-new-friends) to bring yourself back here. This is a bit like the Friend Suggestions page of Facebook. Everybody on this list has agreed that they may be suggested as a friend. @@ -14,8 +14,6 @@ Now you've added one, you're probably lost. Click the link at the top of this page to go back to the suggested friends list and add some more. Feel uncomfortable adding people you don't know? -Don't worry - that's where Groups and Pages come in! +Don't worry - that's where [Groups and Pages](help/quick-start/groups-and-pages) come in! - - diff --git a/doc/quick-start-network.md b/doc/quick-start/network.md similarity index 69% rename from doc/quick-start-network.md rename to doc/quick-start/network.md index 3c97c23c88..0e97747d77 100644 --- a/doc/quick-start-network.md +++ b/doc/quick-start/network.md @@ -1,5 +1,5 @@ This is your Network Tab. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/quick-start/network) to bring yourself back here. This is a bit like the Newsfeed at Facebook or the Stream at Diaspora. It's where all the posts from your contacts, groups, and feeds will appear. @@ -7,8 +7,6 @@ If you're new, you won't see anything in this page, unless you posted your statu If you've already added a few friends, you'll be able to see their posts. Here, you can comment, like, or dislike posts, or click on somebody's name to visit their profile page where you can write on their wall. -Now we need to fill it up, the first step, is to make some new friends. +Now we need to fill it up, the first step, is to [make some new friends](help/quick-start/making-new-friends). - - diff --git a/doc/remove-account.md b/doc/remove-account.md index 83cb941e80..f755762f11 100644 --- a/doc/remove-account.md +++ b/doc/remove-account.md @@ -1,5 +1,4 @@ -Remove Account -============== +# Remove Account * [Home](help) diff --git a/doc/safety.md b/doc/safety.md index 4ecd927e87..bda0c1d85e 100644 --- a/doc/safety.md +++ b/doc/safety.md @@ -1,5 +1,4 @@ -Safety -====== +# Safety * [Home](help) @@ -8,8 +7,7 @@ These servers support a diverse global community of millions of users. Inevitably, some of these users are malicious. Friendica provides several features to keep you safe from abuse and harrassment. -Terms of Service ---- +## Terms of Service Each instance is entitled to define its own Terms of Service, also often called a Code of Conduct. These terms include rules for behaviour. @@ -21,8 +19,7 @@ Remember that conversations frequently involve participants from different insta Participants are only bound by the rules of the server where they have an account, not by the rules of your server. Terms of Service may even be completely incompatible. -Reporting ---- +## Reporting Your local administrators are responsible for ensuring a safe online environment for all users on your server. They rely on reports from users to highlight behaviour that puts other users at risk. @@ -32,8 +29,7 @@ You will be given an opportunity to select the type of problem you are seeing. Your local administrator then has the option of blocking that user for all users on your local instance. If a remote server is a constant source of abuse and their administrators are unable or unwilling to control their users behaviour, your administrator can even block the entire remote server. -Ignoring ---- +## Ignoring Once you have become friends, if you find the person constantly sends you spam or worthless information, you can "Ignore" them - without breaking off the friendship or even alerting them to the fact that you aren't interested in anything they are saying. In many ways they are like a "follower" - but they don't know this. @@ -45,8 +41,7 @@ Some servers are frequent sources of abusive or other unwanted behaviour. For this reason you can also choose to ignore entire servers. Users on that server can still follow you as normal. -Blocking ---- +## Blocking You can also "block" a person. This completely blocks communications with that person. @@ -66,8 +61,7 @@ In some cases this could lead to retaliation. There are several other ways someone can determine that you have blocked them, and see your public posts despite the block. For example, they can simply log out and view your posts. -Archiving ---- +## Archiving Archiving is similar to blocking. However, existing posts this person made before being archived will be visible in your stream. diff --git a/doc/settings.md b/doc/settings.md index 7603a1b2bf..f03bd8fc1c 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -351,11 +351,12 @@ If you want to enable those, you have to activate them in the ``config/local.con Use the following settings to redirect PHP errors to a file. Config: - - error_reporting(E_ERROR | E_WARNING | E_PARSE ); - ini_set('error_log','php.out'); - ini_set('log_errors','1'); - ini_set('display_errors', '0'); +``` +error_reporting(E_ERROR | E_WARNING | E_PARSE ); +ini_set('error_log','php.out'); +ini_set('log_errors','1'); +ini_set('display_errors', '0'); +``` This will put all PHP errors in the file php.out (which must be writeable by the webserver). Undeclared variables are occasionally referenced in the program and therefore we do not recommend using `E_NOTICE` or `E_ALL`. @@ -382,14 +383,15 @@ These are the data base settings, the admin account settings, the path of PHP an ## DB Settings With the following settings, you specify the data base server, the username and password for Friendica and the database to use. - - 'database' => [ - 'hostname' => 'localhost', - 'username' => 'mysqlusername', - 'password' => 'mysqlpassword', - 'database' => 'mysqldatabasename', - 'charset' => 'utf8mb4', - ], +``` +'database' => [ + 'hostname' => 'localhost', + 'username' => 'mysqlusername', + 'password' => 'mysqlpassword', + 'database' => 'mysqldatabasename', + 'charset' => 'utf8mb4', +], +``` ## Admin users @@ -397,31 +399,33 @@ You can set one, or more, accounts to be *Admin*. By default this will be the one account you create during the installation process. But you can expand the list of email addresses by any used email address you want. Registration of new accounts with a listed email address is not possible. - - 'config' => [ - 'admin_email' => 'you@example.com, buddy@example.com', - ], +``` +'config' => [ + 'admin_email' => 'you@example.com, buddy@example.com', +], +``` ## PHP Path Some of Friendica's processes are running in the background. For this you need to specify the path to the PHP binary to be used. - - 'config' => [ - 'php_path' => '/usr/bin/php', - ], +``` +'config' => [ + 'php_path' => '/usr/bin/php', +], +``` ## Subdirectory configuration It is possible to install Friendica into a subdirectory of your web server. We strongly discourage you from doing so, as this will break federation to other networks (e.g. Diaspora, GNU Social, Hubzilla) Say you have a subdirectory for tests and put Friendica into a further subdirectory, the config would be: - - 'system' => [ - 'url' => 'https://example.com/tests/friendica', - ], +``` +'system' => [ + 'url' => 'https://example.com/tests/friendica', +], +``` ## Other exceptions Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/config) section of the documentation. - diff --git a/doc/smarty3-templates.md b/doc/smarty3-templates.md index 0fbe503ebf..2251a0e441 100644 --- a/doc/smarty3-templates.md +++ b/doc/smarty3-templates.md @@ -1,5 +1,4 @@ -Friendica Templating Documentation -================================== +# Friendica Templating Documentation * [Home](help) @@ -21,25 +20,27 @@ Templates that are only used by addons shall be placed in the directory. To render a template use the function *getMarkupTemplate* to load the template and *replaceMacros* to replace the macros/variables in the just loaded template file. - - $tpl = Renderer::getMarkupTemplate('install_settings.tpl'); - $o .= Renderer::replaceMacros($tpl, array( ... )); +```php +$tpl = Renderer::getMarkupTemplate('install_settings.tpl'); +$o .= Renderer::replaceMacros($tpl, array( ... )); +``` the array consists of an association of an identifier and the value for that identifier, i.e. - - '$title' => $install_title, +```php +'$title' => $install_title, +``` where the value may as well be an array by its own. -Form Templates --------------- +## Form Templates To guarantee a consistent look and feel for input forms, i.e. in the settings sections, there are templates for the basic form fields. -They are initialized with an array of data, depending on the tyle of the field. +They are initialized with an array of data, depending on the style of the field. All of these take an array holding the values, e.g. for a one line text input field, which is required and should be used to type email addresses use something along the lines of: - - '$adminmail' => array('adminmail', DI::l10n()->t('Site administrator email address'), $adminmail, DI::l10n()->t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'), +```php +'$adminmail' => array('adminmail', DI::l10n()->t('Site administrator email address'), $adminmail, DI::l10n()->t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'), +``` To evaluate the input value, you can then use the $_POST array, more precisely the $_POST['adminemail'] variable. @@ -148,25 +149,25 @@ Field parameter: ### field_select.tpl -A drop down selection box. +A drop-down selection box. Field parameter: 0. Name of the field, 1. Label of the selection box, 2. Current selected value, 3. Help text for the selection box, -4. Array holding the possible values of the selection drop down. +4. Array holding the possible values of the selection drop-down. ### field_select_raw.tpl -A drop down selection box (see above) but you have to prepare the values yourself. +A drop-down selection box (see above) but you have to prepare the values yourself. Field parameter: 0. Name of the field, 1. Label of the selection box, 2. Current selected value, 3. Help text for the selection box, -4. Possible values of the selection drop down. +4. Possible values of the selection drop-down. ### field_textarea.tpl diff --git a/doc/ssl.md b/doc/ssl.md index d3f5ecc895..a3adff28c6 100644 --- a/doc/ssl.md +++ b/doc/ssl.md @@ -1,5 +1,4 @@ -Using SSL with Friendica -===================================== +# Using SSL with Friendica * [Home](help) @@ -49,7 +48,7 @@ If you run your own server, we recommend to check out the ["Let's Encrypt" initi Not only do they offer free SSL certificates, but also a way to automate their renewal. You need to install a client software on your server to use it. Instructions for the official client are [here](https://certbot.eff.org/). -Depending on your needs, you might want to look at the [list of alternative letsencrypt clients](https://letsencrypt.org/docs/client-options/). +Depending on your needs, you might want to look at the [list of alternative LetsEncrypt clients](https://letsencrypt.org/docs/client-options/). ## Web server settings @@ -70,22 +69,26 @@ This is the simplest way to enforce site-wide secure access. Every time a user tries to access any Friendica page by any mean (manual address bar entry or link), the web server issues a Permanent Redirect response with the secure protocol prepended to the requested URL. With Apache, enable the modules rewrite and ssl (with a shared hosting provider, this should be enabled already): - - sudo a2enmod rewrite ssl +```sh +sudo a2enmod rewrite ssl +``` Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [AlfredSK](https://github.com/AlfredSK)): - RewriteEngine On - RewriteCond %{SERVER_PORT} 80 - RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` +RewriteEngine On +RewriteCond %{SERVER_PORT} 80 +RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` With nginx, configure your server directive this way ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)): - - server { - listen 80; - server_name your.friendica.domain; - return 301 https://$server_name$request_uri; - } +``` +server { + listen 80; + server_name your.friendica.domain; + return 301 https://$server_name$request_uri; +} +``` ### SSL Settings diff --git a/doc/stats.md b/doc/stats.md index 1b6a2dfd2a..cf0986bcad 100644 --- a/doc/stats.md +++ b/doc/stats.md @@ -1,5 +1,4 @@ -Monitoring -=========== +# Monitoring * [Home](help) diff --git a/doc/strategy-hooks.md b/doc/strategy-hooks.md index 3382f7e494..ffc55dfbaf 100644 --- a/doc/strategy-hooks.md +++ b/doc/strategy-hooks.md @@ -1,5 +1,4 @@ -Friendica strategy Hooks -=========================================== +# Friendica strategy Hooks * [Home](help) diff --git a/doc/tags-and-mentions.md b/doc/tags-and-mentions.md index 7c0e2e63bd..6b1ab0b8af 100644 --- a/doc/tags-and-mentions.md +++ b/doc/tags-and-mentions.md @@ -1,13 +1,10 @@ -Tags and Mentions -================= - +# Tags and Mentions * [Home](help) - Like many other modern social networks, Friendica uses a special notation inside messages to indicate "tags" or contextual links to other entities. -**Mentions** +## Mentions People are tagged by preceding their name with the @ character. @@ -41,7 +38,7 @@ If you sort your contacts into circles, you cannot @-mention these circles. But you can select the circle in the access control when creating a new posting, to allow (or disallow) a certain circle of people to see the posting. See [Circles and Privacy](help/circles-and-privacy) for more details about grouping your contacts. -**Topical Tags** +## Topical Tags Topical tags are indicated by preceding the tag name with the # character. This will create a link in the post to a generalised site search for the term provided. diff --git a/doc/text-comment.md b/doc/text-comment.md index 37a91a7dae..29d9723633 100644 --- a/doc/text-comment.md +++ b/doc/text-comment.md @@ -1,32 +1,31 @@ -Comment, sort and delete posts -============== +# Comment, sort and delete posts * [Home](help) Here you can find an overview of the different ways to comment and sort existing posts. Attention: we've used the "diabook" theme. If you're using another theme, some of the icons may be different. -diabook +diabook The different icons -post_thumbs_up.png This symbol is used to indicate that you like the post. Click it twice to undo your choice.

        +post_thumbs_up.png This symbol is used to indicate that you like the post. Click it twice to undo your choice.

        -post_thumbs_down.png This symbol is used to indicate that you dislike the post. Click it twice to undo your choice. +post_thumbs_down.png This symbol is used to indicate that you dislike the post. Click it twice to undo your choice.

        -post_share.png This symbol is used to share a post. A copy of this post will automatically appear in your status editor and add a link to the original post. +post_share.png This symbol is used to share a post. A copy of this post will automatically appear in your status editor and add a link to the original post.

        -post_mark.png This symbol is used to mark a post. Marked posts will appear on your network page at the "starred" tab (from "star"). Click it twice to undo your choice. +post_mark.png This symbol is used to mark a post. Marked posts will appear on your network page at the "starred" tab (from "star"). Click it twice to undo your choice.

        -post_tag.png This symbol is used to tag a post with a self-chosen keyword. When you click at the word, you'll get a list of all posts with this tag. Attention: you can't delete the tag once you've set one. +post_tag.png This symbol is used to tag a post with a self-chosen keyword. When you click at the word, you'll get a list of all posts with this tag. Attention: you can't delete the tag once you've set one.

        -post_categorize.png This symbol is used to categorize posts. Choose an existing folder or create a new one. You'll find the created folder on your network page under the "saved folders" tab. +post_categorize.png This symbol is used to categorize posts. Choose an existing folder or create a new one. You'll find the created folder on your network page under the "saved folders" tab.

        -post_delete.png This symbol is used to delete your own post or to remove a post of another person from your stream. +post_delete.png This symbol is used to delete your own post or to remove a post of another person from your stream.

        -post_choose.png This symbol is used to choose more than one post to delete in a single step. After selecting all posts, go to the end of the page and click "Delete Selected Items".

        +post_choose.png This symbol is used to choose more than one post to delete in a single step. After selecting all posts, go to the end of the page and click "Delete Selected Items".

        diff --git a/doc/text-editor.md b/doc/text-editor.md index 8c8cbfb81d..9ce5624031 100644 --- a/doc/text-editor.md +++ b/doc/text-editor.md @@ -4,8 +4,7 @@ figure img { padding: 2px; } figure figcaption { background: #eeeeee; color: #444444; padding: 2px; font-style: italic;} -Creating posts -=========== +# Creating posts * [Home](help) @@ -15,12 +14,12 @@ One click on the Pencil & Paper icon in the top right of your Home or Network pa Below are examples of the post editor in 3 of Friendica's common themes:
        -frio editor +frio editor
        Post editor, with the Frio (popular default) theme.

        -vier editor +vier editor
        Post editor, with the Vier theme.

        @@ -33,29 +32,29 @@ The Big Empty Textarea is where you write your new post. You can simply enter your text there and click the "Share" button, and your new post will be public on your profile page and shared to your contact. If plain text is not so exciting to you, Friendica understands BBCode to spice up your posts: bold, italic, images, links, lists.. -See [BBCode tags reference](help/bbcode) page to see all what you can do. +See [BBCode tags reference](help/BBCode) page to see all what you can do. The icons under the text area are there to help you to write posts quickly, but vary depending on the theme: With the Frio theme, the Underline, Italics and Bold buttons should be self-explanatory. -editor Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.* In the Frio theme, use the Browser tab instead to Upload and/or attach content to your post. +editor Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.* In the Frio theme, use the Browser tab instead to Upload and/or attach content to your post.

        -paper_clip This depends on the theme: For Frio, this is to attach remote content - put in a URL to embed in your post, including video or audio content. For other themes: Add files from your computer. Same as picture, but for generic attachment to the post.* +paper_clip This depends on the theme: For Frio, this is to attach remote content - put in a URL to embed in your post, including video or audio content. For other themes: Add files from your computer. Same as picture, but for generic attachment to the post.*

        -chain Add a web address (url). Enter a URL and Friendica will add to your post a link to the url and an excerpt from the web site, if possible. +chain Add a web address (url). Enter a URL and Friendica will add to your post a link to the url and an excerpt from the web site, if possible.

        -video Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. (In the Frio theme, this is done with the paperclip as mentioned above.) Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.* +video Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. (In the Frio theme, this is done with the paperclip as mentioned above.) Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.*

        -mic Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud. +mic Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud.

        -globe Or location Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough. +globe Or location Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough.


        @@ -66,21 +65,21 @@ These icons can change depending on the theme. Some examples: - +
        Vier: vier.pngvier.png  
        -* how to [upload](help/faq#upload) files +* how to [upload](help/FAQ#upload) files

         

        -**lock icon The Lock / Permissions** +**lock icon The Lock / Permissions** In Frio, the Permissions tab, or in other themes, the Lock button, is the most important feature in Friendica. If the lock is open, your post will be public, and will show up on your profile page when strangers visit it. Click on it and the *Permission settings* window (aka "*Access Control Selector*" or "*ACL Selector*") pops up. There you can select who can see the post.
        -Permission settings window +Permission settings window
        Permission settings window with some contact selected
        diff --git a/doc/tools.md b/doc/tools.md index fac1f4b392..06930b441e 100644 --- a/doc/tools.md +++ b/doc/tools.md @@ -1,10 +1,8 @@ -Admin Tools -=========== +# Admin Tools * [Home](help) -Friendica Tools ---------------- +## Friendica Tools Friendica has a build in command console you can find in the *bin* directory. The console provides the following commands: @@ -31,8 +29,7 @@ The console provides the following commands: Please consult *bin/console help* on the command line interface of your server for details about the commands. -3rd Party Tools ---------------- +## 3rd Party Tools In addition to the tools Friendica includes, some 3rd party tools can make your admin days easier. @@ -44,21 +41,23 @@ The following configuration was [provided](https://forum.friendi.ca/display/1745 You need to adjust the *logpath* in the *jail.local* file and the *bantime* (value is in seconds). In */etc/fail2ban/jail.local* create a section for Friendica: - - [friendica] - enabled = true - findtime = 300 - bantime = 900 - filter = friendica - port = http,https - logpath = /var/log/friendica.log - logencoding = utf-8 +```toml +[friendica] +enabled = true +findtime = 300 +bantime = 900 +filter = friendica +port = http,https +logpath = /var/log/friendica.log +logencoding = utf-8 +``` And create a filter definition in */etc/fail2ban/filter.d/friendica.conf*: - - [Definition] - failregex = ^.*authenticate\: failed login attempt.*\"ip\"\:\"\".*$ - ignoreregex = +```toml +[Definition] +failregex = ^.*authenticate\: failed login attempt.*\"ip\"\:\"\".*$ +ignoreregex = +``` Additionally you have to define the number of failed logins before the ban should be activated. This is done either in the global configuration or for each jail separately. @@ -73,8 +72,10 @@ To keep them in control you should add them to the automatic [log rotation](http In */etc/logrotate.d/* add a file called *friendica* that contains the configuration. The following will compress */var/log/friendica* (assuming this is the location of the log file) on a daily basis and keep 2 days of back-log. - /var/log/friendica.log { - compress - daily - rotate 2 - } +``` +/var/log/friendica.log { + compress + daily + rotate 2 +} +``` diff --git a/doc/translations.md b/doc/translations.md index 4c84b67a81..db415d8cb6 100644 --- a/doc/translations.md +++ b/doc/translations.md @@ -1,5 +1,4 @@ -Friendica translations -====================== +# Friendica translations * [Home](help) @@ -30,7 +29,7 @@ We currently support the gettext version 0.19.8.1 and actively check new transla If you don't use this version, it's possible that our checks fail (f.e. because of tiny differences at linebreaks). In case you do have a Docker environment, you can easily update the translations with the following command: -```shell +```sh docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh ``` @@ -43,9 +42,10 @@ Once you have added new translation strings in your code changes, please run `bi If you have the `friendica-addons` repository in the `addon` directory of your Friendica cloned repository, just run `bin/run_xgettext.sh -a ` from the base Friendica directory. Otherwise: - - cd /path/to/friendica-addons/ - /path/to/friendica/bin/run_xgettext.sh -s +```sh +cd /path/to/friendica-addons/ +/path/to/friendica/bin/run_xgettext.sh -s +``` In either case, you need to commit the updated `/lang/C/messages.po` to your working branch. @@ -65,17 +65,19 @@ After installation of the client, you should have a `tx` command available on yo To use it, first create a configuration file with your credentials. On Linux this file should be placed into your home directory `~/.transifexrc`. The content of the file should be something like the following: - - [https://app.transifex.com] - username = user - token = - password = p@ssw0rd - hostname = https://app.transifex.com +```toml +[https://app.transifex.com] +username = user +token = +password = p@ssw0rd +hostname = https://app.transifex.com +``` Since Friendica version 3.5.1 we ship configuration files for the Transifex client in the core repository and the addon repository in `.tx/config`. To update the PO files after you have translated strings of e.g. Esperanto on the Transifex website you can use `tx` to download the updated PO file in the right location. - - $> tx pull -l eo +```sh +tx pull -l eo +``` Then run `bin/console po2php view/lang//messages.po` to update the related `strings.php` file and commit both files to your working branch. diff --git a/doc/update.md b/doc/update.md index b6c5c53e19..29614bca32 100644 --- a/doc/update.md +++ b/doc/update.md @@ -1,5 +1,4 @@ -Updating Friendica -=============== +# Updating Friendica * [Home](help) @@ -27,15 +26,17 @@ To update Addons from an archive, simply delete the ``path/to/friendica/addon`` ## Using Git You can get the latest changes at any time with - - cd path/to/friendica - git pull - bin/composer.phar run install:prod +```sh +cd path/to/friendica +git pull +bin/composer.phar run install:prod +``` The addon tree has to be updated separately like so: - - cd path/to/friendica/addon - git pull +```sh +cd path/to/friendica/addon +git pull +``` For both repositories: The default branch to use is the ``stable`` branch, which is the stable version of Friendica. @@ -61,7 +62,7 @@ There are two main ways of doing it, either by manually removing the duplicates Manually removing the duplicates is usually faster if they're not too numerous. To manually remove the duplicates, you need to know the UNIQUE index columns available in `database.sql`. -```SQL +```sql SELECT GROUP_CONCAT(id), , count(*) as count FROM users GROUP BY HAVING count >= 2; @@ -71,7 +72,7 @@ GROUP BY HAVING count >= 2; If there are too many rows to handle manually, you can create a new table with the same structure as the table with duplicates and insert the existing content with INSERT IGNORE. To recreate the table you need to know the table structure available in `database.sql`. -```SQL +```sql CREATE TABLE _new ; INSERT IGNORE INTO _new SELECT * FROM ; DROP TABLE ; @@ -84,7 +85,7 @@ This method is slower overall, but it is better suited for large numbers of dupl #### Foreign Keys -Some of the updates include the use of foreign keys now that will bump into issues with previous versions, which would sometimes shove bad data into tables, preventing, causing errors such as below. +Some updates include the use of foreign keys now that will bump into issues with previous versions, which would sometimes shove bad data into tables, preventing, causing errors such as below. ``` Error 1452 occurred during database update: @@ -94,7 +95,7 @@ ALTER TABLE `thread` ADD FOREIGN KEY (`iid`) REFERENCES `item` (`id`) ON UPDATE All current known fixes for possible items that can go wrong are as below. -```SQL +```sql DELETE FROM `item` WHERE `owner-id` NOT IN (SELECT `id` FROM `contact`); DELETE FROM `item` WHERE `contact-id` NOT IN (SELECT `id` FROM `contact`); DELETE FROM `notify` WHERE `uri-id` NOT IN (SELECT `id` FROM `item-uri`); diff --git a/doc/vagrant.md b/doc/vagrant.md index 29a2871bd8..9c433b4b5e 100644 --- a/doc/vagrant.md +++ b/doc/vagrant.md @@ -1,16 +1,14 @@ -Vagrant for Friendica Developers -=================== +# Vagrant for Friendica Developers * [Home](help) -Getting started ---------------- +## Getting started [Vagrant](https://www.vagrantup.com/) is a virtualization solution for developers. No need to setup up a webserver, database etc. before actually starting. Vagrant creates a virtual machine for you that you can just run inside VirtualBox and start to work directly on Friendica. -It brings an Debian Bullseye with PHP 8.0 and MariaDB 10.5.11. +It brings a Debian Bullseye with PHP 8.0 and MariaDB 10.5.11. What you need to do: @@ -34,22 +32,24 @@ Find the Friendica log file `/vagrant/logfile.out` on the VM or in the `logfile. 8. Commit and push your changes directly back to GitHub. If you want to stop vagrant after finishing your work, run the following command - - $> vagrant halt +```sh +vagrant halt +``` in the development directory. This will not delete the virtual machine. 9. To ultimately delete the virtual machine run - - $> vagrant destroy - $> rm /vagrant/config/local.config.php +```sh +vagrant destroy +rm /vagrant/config/local.config.php +``` to make sure that you can start from scratch with another "vagrant up". Default User Accounts --------------------- -By default the provision script will setup two user accounts. +By default the provision script will set up two user accounts. * admin, password admin * friendica, password friendica @@ -57,10 +57,11 @@ By default the provision script will setup two user accounts. Trouble Shooting ---------------- -If you see a version mis-match for the _VirtualBox Guest Additions_ between host and guest during the initial setup of the Vagrant VM, you will need to install an addon to Vagrant (ref. [Stack Overflow](https://stackoverflow.com/a/38010683)). +If you see a version mismatch for the _VirtualBox Guest Additions_ between host and guest during the initial setup of the Vagrant VM, you will need to install an addon to Vagrant (ref. [Stack Overflow](https://stackoverflow.com/a/38010683)). Stop the Vagrant VM and run the following command: - - $> vagrant plugin install vagrant-vbguest +```sh +vagrant plugin install vagrant-vbguest +``` On the next Vagrant up, the version problem should be fixed. diff --git a/src/Module/Help.php b/src/Module/Help.php index 67645a7732..f68d5d45c8 100644 --- a/src/Module/Help.php +++ b/src/Module/Help.php @@ -114,6 +114,13 @@ class Help extends BaseModule { $baseName = basename($fileName); $dirName = dirname($fileName); + // An ugly hack to get the guide, which is inside a directory now, working again in German + // A non-hacky solution could be found, but if this file is being deleted soon when switching to mkdocs then...? + if (strpos($dirName, "quick-start")) { + if (file_exists("doc/$lang/quick-start/$baseName")) { + return file_get_contents("doc/$lang/quick-start/$baseName"); + } + } if (file_exists("$dirName/$lang/$baseName")) { return file_get_contents("$dirName/$lang/$baseName"); } diff --git a/view/templates/welcome.tpl b/view/templates/welcome.tpl index f8f4141a3f..d4f96e292c 100644 --- a/view/templates/welcome.tpl +++ b/view/templates/welcome.tpl @@ -12,7 +12,7 @@

        {{$started nofilter}}

        diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php index 4b26100c0f..bd1fe9accc 100644 --- a/view/theme/vier/theme.php +++ b/view/theme/vier/theme.php @@ -218,7 +218,7 @@ function vier_community_info() $r[$index]["url"] = Contact::magicLink($helper["url"]); } - $r[] = ["url" => "help/quick-start-guide", "name" => DI::l10n()->t("Quick Start")]; + $r[] = ["url" => "help/quick-start/guide", "name" => DI::l10n()->t("Quick Start")]; $tpl = Renderer::getMarkupTemplate('ch_helpers.tpl'); From d2706b8f931ce14c4d3b12d0c127616ced52e220 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Tue, 14 Oct 2025 11:39:21 +0200 Subject: [PATCH 012/138] Docs: Missing non-lowercase references to docs --- doc/de/settings.md | 2 +- doc/de/text-editor.md | 2 +- doc/settings.md | 2 +- doc/text-editor.md | 4 ++-- view/templates/settings/twofactor/app_specific.tpl | 2 +- view/templates/settings/twofactor/index.tpl | 2 +- view/templates/settings/twofactor/recovery.tpl | 2 +- view/templates/settings/twofactor/trusted_browsers.tpl | 2 +- view/templates/settings/twofactor/verify.tpl | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/de/settings.md b/doc/de/settings.md index 68d639cb5f..c1a1d06312 100644 --- a/doc/de/settings.md +++ b/doc/de/settings.md @@ -65,7 +65,7 @@ Dabei kannst du zwischen den folgenden Optionen wählen: ##### Einladungen Zusätzlich zu den oben genannten Möglichkeiten, kann die Registrierung eines neuen Nutzerkontos an eine Einladung durch einen bestehenden Nutzer gekoppelt werden. -Hierzu muss in der [config/local.config.php](/help/Config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. +Hierzu muss in der [config/local.config.php](/help/config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. #### Namen auf Vollständigkeit überprüfen diff --git a/doc/de/text-editor.md b/doc/de/text-editor.md index 3b21f92c89..39f0679f0e 100644 --- a/doc/de/text-editor.md +++ b/doc/de/text-editor.md @@ -41,7 +41,7 @@ Hier reicht schon eine Angabe wie "Berlin" oder "10775". Dieser Eintrag führt anschließend zu einer Suchanfrage bei Google Maps.

        -* wie du Dateien hochladen kannst, erfährst du [hier](help/FAQ#upload) +* wie du Dateien hochladen kannst, erfährst du [hier](help/faq#upload) **Im Folgenden findest du Symbole weiterer Themen** diff --git a/doc/settings.md b/doc/settings.md index f03bd8fc1c..e28c9e37c6 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -73,7 +73,7 @@ You can chose between the following modes: ##### Invitation based registry Additionally to the setting in the admin panel, you can decide if registrations are only possible using an invitation code or not. -To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/Config) file. +To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/config) file. If you want to use this method, the registration policy has to be set to either *open* or *requires approval*. #### Check Display Names diff --git a/doc/text-editor.md b/doc/text-editor.md index 9ce5624031..a2c0ef798e 100644 --- a/doc/text-editor.md +++ b/doc/text-editor.md @@ -32,7 +32,7 @@ The Big Empty Textarea is where you write your new post. You can simply enter your text there and click the "Share" button, and your new post will be public on your profile page and shared to your contact. If plain text is not so exciting to you, Friendica understands BBCode to spice up your posts: bold, italic, images, links, lists.. -See [BBCode tags reference](help/BBCode) page to see all what you can do. +See [BBCode tags reference](help/bbcode) page to see all what you can do. The icons under the text area are there to help you to write posts quickly, but vary depending on the theme: @@ -69,7 +69,7 @@ These icons can change depending on the theme. Some examples:   -* how to [upload](help/FAQ#upload) files +* how to [upload](help/faq#upload) files

         

        **lock icon The Lock / Permissions** diff --git a/view/templates/settings/twofactor/app_specific.tpl b/view/templates/settings/twofactor/app_specific.tpl index 8adf7e9c31..c457a930d6 100644 --- a/view/templates/settings/twofactor/app_specific.tpl +++ b/view/templates/settings/twofactor/app_specific.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
        -

        {{$title}}

        +

        {{$title}}

        {{$message nofilter}}
        {{if $generated_app_specific_password}} diff --git a/view/templates/settings/twofactor/index.tpl b/view/templates/settings/twofactor/index.tpl index 1832a09d0d..cd1919aee4 100644 --- a/view/templates/settings/twofactor/index.tpl +++ b/view/templates/settings/twofactor/index.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
        -

        {{$title}}

        +

        {{$title}}

        {{$message nofilter}}

        {{$status_title}}

        {{$auth_app_label}}: {{$app_status}}

        diff --git a/view/templates/settings/twofactor/recovery.tpl b/view/templates/settings/twofactor/recovery.tpl index 08d1c2e7c5..198f7daaee 100644 --- a/view/templates/settings/twofactor/recovery.tpl +++ b/view/templates/settings/twofactor/recovery.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
        -

        {{$title}}

        +

        {{$title}}

        {{$message nofilter}}
          diff --git a/view/templates/settings/twofactor/trusted_browsers.tpl b/view/templates/settings/twofactor/trusted_browsers.tpl index 56464e55b9..2d19961612 100644 --- a/view/templates/settings/twofactor/trusted_browsers.tpl +++ b/view/templates/settings/twofactor/trusted_browsers.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
          -

          {{$title}}

          +

          {{$title}}

          {{$message nofilter}}
          diff --git a/view/templates/settings/twofactor/verify.tpl b/view/templates/settings/twofactor/verify.tpl index 8329c9a36b..42f8b4649c 100644 --- a/view/templates/settings/twofactor/verify.tpl +++ b/view/templates/settings/twofactor/verify.tpl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later *}}
          -

          {{$title}}

          +

          {{$title}}

          {{$message nofilter}}
          From c7ba9ac95d7ae44189b7a2562da68d274a750621 Mon Sep 17 00:00:00 2001 From: Marcus Funch Date: Wed, 15 Oct 2025 18:35:29 +0200 Subject: [PATCH 013/138] Docs: Update directory structure (credits to nupplaphil) --- doc/de/{faq-admin.md => admin/faq.md} | 2 + doc/de/{ => admin}/improve-performance.md | 0 doc/de/{ => admin}/install.md | 0 doc/de/{ => admin}/installing-connectors.md | 0 doc/de/{ => admin}/settings.md | 8 +- doc/de/{ => admin}/ssl.md | 0 .../addon-development.md} | 0 doc/de/{developers.md => developer/guide.md} | 0 doc/de/guide.md | 25 ----- doc/de/home.md | 97 +++++++++--------- doc/de/{ => spec/protocol}/message-flow.md | 0 doc/de/{ => user}/account-basics.md | 0 doc/de/{ => user}/bbcode.md | 0 doc/de/{ => user}/bugs-and-issues.md | 0 doc/de/{ => user}/channels.md | 0 doc/de/{ => user}/chats.md | 0 doc/de/{ => user}/circles-and-privacy.md | 0 doc/de/{ => user}/connectors.md | 0 doc/de/{ => user}/events.md | 0 doc/de/{ => user}/export-import-contacts.md | 0 doc/de/{ => user}/faq.md | 2 + doc/de/{ => user}/groups.md | 0 doc/de/{ => user}/making-friends.md | 0 doc/de/{ => user}/move-account.md | 0 doc/de/{ => user}/quick-start/finally.md | 2 +- .../quick-start/groups-and-pages.md | 2 +- doc/de/{ => user}/quick-start/guide.md | 2 +- .../quick-start/making-new-friends.md | 4 +- doc/de/{ => user}/quick-start/network.md | 4 +- doc/de/{ => user}/remove-account.md | 0 doc/de/{ => user}/tags-and-mentions.md | 0 doc/de/{ => user}/text-comment.md | 0 doc/de/{ => user}/text-editor.md | 0 doc/{ => en/admin}/config.md | 0 doc/{faq-admin.md => en/admin/faq.md} | 12 ++- doc/{ => en/admin}/improve-performance.md | 0 doc/{ => en/admin}/install-ejabberd.md | 0 doc/{ => en/admin}/install.md | 2 +- doc/{ => en/admin}/installing-connectors.md | 0 doc/{ => en/admin}/migrate.md | 0 doc/{ => en/admin}/settings.md | 8 +- doc/{ => en/admin}/ssl.md | 0 doc/{ => en/admin}/stats.md | 0 doc/{ => en/admin}/tools.md | 0 doc/{ => en/admin}/update.md | 0 .../developer/addon-development.md} | 0 .../developer}/addon-storage-backend.md | 0 doc/{ => en/developer}/autoloader.md | 8 +- doc/{ => en/developer}/composer.md | 10 +- .../developer/domain-driven-design.md} | 0 doc/{ => en/developer}/github.md | 2 +- .../developer/how-to-move-classes-to-src.md} | 10 +- .../developer/index.md} | 12 +-- doc/{ => en/developer}/smarty3-templates.md | 0 doc/{ => en/developer}/strategy-hooks.md | 0 doc/{ => en/developer}/tests.md | 0 doc/{ => en/developer}/themes.md | 0 doc/{ => en/developer}/translations.md | 0 doc/{ => en/developer}/vagrant.md | 0 doc/en/home.md | 80 +++++++++++++++ .../spec/api/entities.md} | 50 ++++----- .../spec/api/friendica.md} | 36 +++---- .../spec/api/gnu-social.md} | 6 +- doc/{api.md => en/spec/api/index.md} | 0 .../spec/api/mastodon.md} | 6 +- .../spec/api/twitter.md} | 6 +- doc/{ => en/spec}/message-flow.md | 0 doc/{ => en}/spec/protocol/dfrn-snap2.jpg | Bin doc/{ => en}/spec/protocol/dfrn2.odt | Bin doc/{ => en}/spec/protocol/dfrn2.pdf | Bin .../protocol/dfrn2_contact_confirmation.png | Bin .../protocol/dfrn2_contact_confirmation.svg | 0 .../spec/protocol/dfrn2_contact_request.png | Bin .../spec/protocol/dfrn2_contact_request.svg | 0 doc/{ => en/spec/protocol}/protocol.md | 2 +- doc/{ => en}/spec/protocol/zot-2012.txt | 0 doc/{ => en}/spec/protocol/zot.txt | 0 doc/{ => en/user}/access-keys.md | 0 doc/{ => en/user}/account-basics.md | 0 doc/{ => en/user}/bbcode.md | 2 +- doc/{ => en/user}/bugs-and-issues.md | 0 doc/{ => en/user}/channels.md | 0 doc/{ => en/user}/chats.md | 0 doc/{ => en/user}/circles-and-privacy.md | 0 doc/{ => en/user}/connectors.md | 0 doc/{ => en/user}/events.md | 0 doc/{ => en/user}/export-import-contacts.md | 2 +- doc/{ => en/user}/faq.md | 29 +++--- doc/{ => en/user}/groups.md | 0 doc/{ => en/user}/keyboard-shortcuts.md | 0 doc/{ => en/user}/making-friends.md | 0 doc/{ => en/user}/move-account.md | 0 doc/{ => en/user}/quick-start/finally.md | 2 +- .../user}/quick-start/groups-and-pages.md | 4 +- doc/{ => en/user}/quick-start/guide.md | 2 +- .../user}/quick-start/making-new-friends.md | 4 +- doc/{ => en/user}/quick-start/network.md | 4 +- doc/{ => en/user}/remove-account.md | 0 doc/{ => en/user}/safety.md | 0 doc/{ => en/user}/tags-and-mentions.md | 0 doc/{ => en/user}/text-comment.md | 0 doc/{ => en/user}/text-editor.md | 0 .../user}/two-factor-authentication.md | 0 doc/home.md | 79 -------------- src/Module/Admin/Summary.php | 2 +- src/Module/Help.php | 34 +++--- view/theme/vier/theme.php | 2 +- 107 files changed, 273 insertions(+), 291 deletions(-) rename doc/de/{faq-admin.md => admin/faq.md} (97%) rename doc/de/{ => admin}/improve-performance.md (100%) rename doc/de/{ => admin}/install.md (100%) rename doc/de/{ => admin}/installing-connectors.md (100%) rename doc/de/{ => admin}/settings.md (98%) rename doc/de/{ => admin}/ssl.md (100%) rename doc/de/{addons.md => developer/addon-development.md} (100%) rename doc/de/{developers.md => developer/guide.md} (100%) delete mode 100644 doc/de/guide.md rename doc/de/{ => spec/protocol}/message-flow.md (100%) rename doc/de/{ => user}/account-basics.md (100%) rename doc/de/{ => user}/bbcode.md (100%) rename doc/de/{ => user}/bugs-and-issues.md (100%) rename doc/de/{ => user}/channels.md (100%) rename doc/de/{ => user}/chats.md (100%) rename doc/de/{ => user}/circles-and-privacy.md (100%) rename doc/de/{ => user}/connectors.md (100%) rename doc/de/{ => user}/events.md (100%) rename doc/de/{ => user}/export-import-contacts.md (100%) rename doc/de/{ => user}/faq.md (99%) rename doc/de/{ => user}/groups.md (100%) rename doc/de/{ => user}/making-friends.md (100%) rename doc/de/{ => user}/move-account.md (100%) rename doc/de/{ => user}/quick-start/finally.md (85%) rename doc/de/{ => user}/quick-start/groups-and-pages.md (96%) rename doc/de/{ => user}/quick-start/guide.md (97%) rename doc/de/{ => user}/quick-start/making-new-friends.md (91%) rename doc/de/{ => user}/quick-start/network.md (90%) rename doc/de/{ => user}/remove-account.md (100%) rename doc/de/{ => user}/tags-and-mentions.md (100%) rename doc/de/{ => user}/text-comment.md (100%) rename doc/de/{ => user}/text-editor.md (100%) rename doc/{ => en/admin}/config.md (100%) rename doc/{faq-admin.md => en/admin/faq.md} (91%) rename doc/{ => en/admin}/improve-performance.md (100%) rename doc/{ => en/admin}/install-ejabberd.md (100%) rename doc/{ => en/admin}/install.md (99%) rename doc/{ => en/admin}/installing-connectors.md (100%) rename doc/{ => en/admin}/migrate.md (100%) rename doc/{ => en/admin}/settings.md (98%) rename doc/{ => en/admin}/ssl.md (100%) rename doc/{ => en/admin}/stats.md (100%) rename doc/{ => en/admin}/tools.md (100%) rename doc/{ => en/admin}/update.md (100%) rename doc/{addons.md => en/developer/addon-development.md} (100%) rename doc/{ => en/developer}/addon-storage-backend.md (100%) rename doc/{ => en/developer}/autoloader.md (96%) rename doc/{ => en/developer}/composer.md (93%) rename doc/{developer-domain-driven-design.md => en/developer/domain-driven-design.md} (100%) rename doc/{ => en/developer}/github.md (97%) rename doc/{developer-how-to-move-classes-to-src.md => en/developer/how-to-move-classes-to-src.md} (93%) rename doc/{developers-intro.md => en/developer/index.md} (97%) rename doc/{ => en/developer}/smarty3-templates.md (100%) rename doc/{ => en/developer}/strategy-hooks.md (100%) rename doc/{ => en/developer}/tests.md (100%) rename doc/{ => en/developer}/themes.md (100%) rename doc/{ => en/developer}/translations.md (100%) rename doc/{ => en/developer}/vagrant.md (100%) create mode 100644 doc/en/home.md rename doc/{api-entities.md => en/spec/api/entities.md} (93%) rename doc/{api-friendica.md => en/spec/api/friendica.md} (94%) rename doc/{api-gnu-social.md => en/spec/api/gnu-social.md} (92%) rename doc/{api.md => en/spec/api/index.md} (100%) rename doc/{api-mastodon.md => en/spec/api/mastodon.md} (99%) rename doc/{api-twitter.md => en/spec/api/twitter.md} (99%) rename doc/{ => en/spec}/message-flow.md (100%) rename doc/{ => en}/spec/protocol/dfrn-snap2.jpg (100%) rename doc/{ => en}/spec/protocol/dfrn2.odt (100%) rename doc/{ => en}/spec/protocol/dfrn2.pdf (100%) rename doc/{ => en}/spec/protocol/dfrn2_contact_confirmation.png (100%) rename doc/{ => en}/spec/protocol/dfrn2_contact_confirmation.svg (100%) rename doc/{ => en}/spec/protocol/dfrn2_contact_request.png (100%) rename doc/{ => en}/spec/protocol/dfrn2_contact_request.svg (100%) rename doc/{ => en/spec/protocol}/protocol.md (93%) rename doc/{ => en}/spec/protocol/zot-2012.txt (100%) rename doc/{ => en}/spec/protocol/zot.txt (100%) rename doc/{ => en/user}/access-keys.md (100%) rename doc/{ => en/user}/account-basics.md (100%) rename doc/{ => en/user}/bbcode.md (99%) rename doc/{ => en/user}/bugs-and-issues.md (100%) rename doc/{ => en/user}/channels.md (100%) rename doc/{ => en/user}/chats.md (100%) rename doc/{ => en/user}/circles-and-privacy.md (100%) rename doc/{ => en/user}/connectors.md (100%) rename doc/{ => en/user}/events.md (100%) rename doc/{ => en/user}/export-import-contacts.md (87%) rename doc/{ => en/user}/faq.md (93%) rename doc/{ => en/user}/groups.md (100%) rename doc/{ => en/user}/keyboard-shortcuts.md (100%) rename doc/{ => en/user}/making-friends.md (100%) rename doc/{ => en/user}/move-account.md (100%) rename doc/{ => en/user}/quick-start/finally.md (81%) rename doc/{ => en/user}/quick-start/groups-and-pages.md (88%) rename doc/{ => en/user}/quick-start/guide.md (95%) rename doc/{ => en/user}/quick-start/making-new-friends.md (80%) rename doc/{ => en/user}/quick-start/network.md (79%) rename doc/{ => en/user}/remove-account.md (100%) rename doc/{ => en/user}/safety.md (100%) rename doc/{ => en/user}/tags-and-mentions.md (100%) rename doc/{ => en/user}/text-comment.md (100%) rename doc/{ => en/user}/text-editor.md (100%) rename doc/{ => en/user}/two-factor-authentication.md (100%) delete mode 100644 doc/home.md diff --git a/doc/de/faq-admin.md b/doc/de/admin/faq.md similarity index 97% rename from doc/de/faq-admin.md rename to doc/de/admin/faq.md index 66c41fa15a..4286ac2be1 100644 --- a/doc/de/faq-admin.md +++ b/doc/de/admin/faq.md @@ -2,6 +2,8 @@ * [Zur Startseite der Hilfe](help) + + * **[Kann ich mehrere Domains mit den selben Dateien aufsetzen?](help/faq-admin#multiple)** * **[Wo kann ich den Quellcode von Friendica, Addons und Themes finden?](help/faq-admin#sources)** * **[Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden?](help/faq-admin#adminaccount1)** diff --git a/doc/de/improve-performance.md b/doc/de/admin/improve-performance.md similarity index 100% rename from doc/de/improve-performance.md rename to doc/de/admin/improve-performance.md diff --git a/doc/de/install.md b/doc/de/admin/install.md similarity index 100% rename from doc/de/install.md rename to doc/de/admin/install.md diff --git a/doc/de/installing-connectors.md b/doc/de/admin/installing-connectors.md similarity index 100% rename from doc/de/installing-connectors.md rename to doc/de/admin/installing-connectors.md diff --git a/doc/de/settings.md b/doc/de/admin/settings.md similarity index 98% rename from doc/de/settings.md rename to doc/de/admin/settings.md index c1a1d06312..681a21f334 100644 --- a/doc/de/settings.md +++ b/doc/de/admin/settings.md @@ -41,7 +41,7 @@ Sie wird verwendet, wenn es Friendica nicht gelingt die Spracheinstellungen des Nutzer können diese Auswahl in den Einstellungen des Benutzerkontos überschreiben. Die Friendica Gemeinschaft bietet einige Übersetzungen an, von denen einige mehr andere weniger komplett sind. -Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/translations) der Dokumentation. +Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/developer/translations) der Dokumentation. #### Systemweites Theme @@ -65,7 +65,7 @@ Dabei kannst du zwischen den folgenden Optionen wählen: ##### Einladungen Zusätzlich zu den oben genannten Möglichkeiten, kann die Registrierung eines neuen Nutzerkontos an eine Einladung durch einen bestehenden Nutzer gekoppelt werden. -Hierzu muss in der [config/local.config.php](/help/config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. +Hierzu muss in der [config/local.config.php](/help/admin/config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. #### Namen auf Vollständigkeit überprüfen @@ -105,7 +105,7 @@ Falls ein solches verwendet wird, sei an dieser Stelle nur auf deren Dokumentati Die Grundeinstellung ist 'Datenbank (legacy)': Dies ist die alte Methode von Friendica Daten direkt in der Datenbank abzulegen. Bestehende Daten können zum aktuell ausgewählten Backend verschoben werden. -Hierfür kann der ['storage move'](help/tools) Befehl der Friendica Konsole verwendet werden. +Hierfür kann der ['storage move'](help/admin/tools) Befehl der Friendica Konsole verwendet werden. Sollte das ausgewählte Speicher Backand zusätzliche Konfigurationsparameter besitzen, werden nach der Auswahl des Backends hier weitere Felder angezeigt. @@ -425,4 +425,4 @@ Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein w ## Weitere Ausnahmen Es gibt noch einige experimentelle Einstellungen, die nur in der ``config/local.config.php`` Datei konfiguriert werden können. -Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/config) Artikel kannst du mehr darüber erfahren. +Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/admin/config) Artikel kannst du mehr darüber erfahren. diff --git a/doc/de/ssl.md b/doc/de/admin/ssl.md similarity index 100% rename from doc/de/ssl.md rename to doc/de/admin/ssl.md diff --git a/doc/de/addons.md b/doc/de/developer/addon-development.md similarity index 100% rename from doc/de/addons.md rename to doc/de/developer/addon-development.md diff --git a/doc/de/developers.md b/doc/de/developer/guide.md similarity index 100% rename from doc/de/developers.md rename to doc/de/developer/guide.md diff --git a/doc/de/guide.md b/doc/de/guide.md deleted file mode 100644 index 021d48b25a..0000000000 --- a/doc/de/guide.md +++ /dev/null @@ -1,25 +0,0 @@ -# Erste Schritte... - -* [Zur Startseite der Hilfe](help) - -Das Erste zum Anfang: geh sicher, dass du schon eingeloggt bist. -Wenn du noch nicht eingeloggt bist, kannst du das in dem Fenster unten machen. - -Sobald du eingeloggt bist (oder wenn du bereits eingeloggt bist), kannst du unten nun auf deine Profilseite schauen. - -Hier sieht es ein wenig wie auf deiner Facebook-Seite aus. -Hier findest du alle deine Statusmeldungen und Nachrichten deiner Freunde, die direkt auf deine Seite ("Wall") geschrieben haben. -Um deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. -Wenn du das machst, vergrößert sich die Box. -Nun kannst du einige Formatierungsoptionen wie Fett, kursiv, unterstrichen auswählen und ebenfalls Bilder und Links hinzufügen. -Unten findest du in diesem Feld weitere Links, mit denen du Bilder und Dateien von deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. -Außerdem kannst du hier eintragen, wo du gerade bist. - -Wenn du deinen Beitrag ("Post") geschrieben hast, kannst du auf das "Schloss"-Symbol klicken und festlegen, wer deinen Beitrag sehen kann. -Wenn du dieses Symbol nicht anklickst, ist dein Beitrag öffentlich. -Das bedeutet, dass jeder, der dein Profil ansieht, der auf dem "Community"-Tab deines Servers oder auf dem "Netzwerk"-Tab ("Beiträge deiner Kontakte") eines befreundeten Kontakts ist, den Beitrag sehen kann. - -Probiere es doch einfach mal aus. Wenn du fertg bist, schauen wir uns den "Netzwerk"-Tab an. - - - diff --git a/doc/de/home.md b/doc/de/home.md index d11f6407e3..f6c0856dfa 100644 --- a/doc/de/home.md +++ b/doc/de/home.md @@ -1,65 +1,62 @@ # Hilfe -**Dokumentation für Benutzer** +## Dokumentation für Benutzer * Allgemeine Funktionen - Erste Schritte - * [Account - Basics](help/account-basics) - * [Schnellstart für neue Benutzer](help/quick-start/guide) - * [Beiträge erstellen](help/text-editor) - * [Referenz der BBCode Elemente](help/bbcode) - * [Beiträge kommentieren, einordnen und löschen](help/text-comment) - * [Referenz der Accesskeys](help/access-keys) - * [Veranstaltungen](help/events) + * [Account - Basics](help/user/account-basics) + * [Schnellstart für neue Benutzer](help/user/quick-start/guide) + * [Beiträge erstellen](help/user/text-editor) + * [Referenz der BBCode Elemente](help/user/bbcode) + * [Beiträge kommentieren, einordnen und löschen](help/user/text-comment) + * [Referenz der Accesskeys](help/user/access-keys) (EN) + * [Veranstaltungen](help/user/events) * Du und andere Nutzer - * [Konnektoren (Connectors)](help/connectors) - * [Freunde finden](help/making-friends) - * [Circles und Privatsphäre](help/circles-and-privacy) - * [Tags und Erwähnungen](help/tags-and-mentions) - * [Community-Gruppen](help/groups) - * [Kanäle (Channels)](help/channels) - * [Chats](help/chats) + * [Konnektoren (Connectors)](help/user/connectors) + * [Freunde finden](help/user/making-friends) + * [Circles und Privatsphäre](help/user/circles-and-privacy) + * [Tags und Erwähnungen](help/user/tags-and-mentions) + * [Gruppen](help/user/groups) + * [Kanäle (Channels)](help/user/channels) + * [Chats](help/user/chats) * Weiterführende Informationen - * [Account umziehen](help/move-account) - * [Export / Import gefolgter Kontakte](help/export-import-contacts) - * [Account löschen](help/remove-account) - * [Bugs und Probleme](help/bugs-and-issues) - * [Häufig gestellte Fragen (FAQ)](help/faq) + * [Häufig gestellte Fragen (FAQ)](help/user/faq) + * [Account umziehen](help/user/move-account) + * [Export / Import gefolgter Kontakte](help/user/export-import-contacts) + * [Account löschen](help/user/remove-account) + * [Bugs und Probleme](help/user/bugs-and-issues) -**Dokumentation für Administratoren** +## Dokumentation für Administratoren -* [Installation](help/install) -* [Update](help/update) (EN) -* [Konfigurationen & Admin-Panel](help/settings) -* [Addons](help/addons) -* [Konnektoren (Connectors) installieren](help/installing-connectors) -* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN) -* [Betreibe deine Seite mit einem SSL-Zertifikat](help/ssl) -* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/config) (EN) -* [Performance verbessern](help/improve-performance) -* [Administration Werkzeuge](help/tools) (EN) -* [Admin FAQ](help/faq-admin) +* [Häufig gestellte Fragen FAQ](help/admin/faq) +* [Installation](help/admin/install) +* [Update](help/admin/update) (EN) +* [Konfigurationen & Admin-Panel](help/admin/settings) +* [Konnektoren (Connectors) installieren](help/admin/installing-connectors) +* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/admin/install-ejabberd) (EN) +* [Betreibe deine Seite mit einem SSL-Zertifikat](help/admin/ssl) +* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/admin/config) (EN) +* [Performance verbessern](help/admin/improve-performance) +* [Administration Werkzeuge](help/admin/tools) (EN) -**Dokumentation für Entwickler** +## Dokumentation für Entwickler -* [Entwickler](help/developers) -* [Where to get started?](help/developers-intro) (EN) -* [Help on Github](help/github) -* [Help on Vagrant](help/vagrant) -* [How to translate Friendica](help/translations) (EN) -* [Bugs and Issues](help/bugs-and-issues) -* [Addon Development](help/addons) -* [Theme Development](help/themes) -* [Smarty 3 Templates](help/smarty3-templates) -* [Protokoll Dokumentation](help/protocol) (EN) +* [Guide](help/developer/guide) +* [Where to get started?](help/developer/index) (EN) +* [On GitHub](help/developer/github) +* [On Vagrant](help/developer/vagrant) +* [Translate Friendica](help/developer/translations) (EN) +* [Addon Development](help/developer/addons) +* [Theme Development](help/developer/themes) +* [Smarty 3 Templates](help/developer/smarty3-templates) +* [Protokoll Dokumentation](help/spec/protocol/procotol) (EN) * [Datenbank-Schema](help/database) -* [Class Autoloading](help/autoloader) (EN) -* [Using Composer](help/composer) (EN) +* [Class Autoloading](help/developer/autoloader) (EN) +* [Using Composer](help/developer/composer) (EN) * [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/) -* [API Dokumentation](help/api) (EN) -* [Translation of Friendica](help/translations) (EN) -* [Run tests](help/tests) (EN) +* [API Dokumentation](help/spec/api/index) (EN) +* [Run tests](help/developer/tests) (EN) -**Links** +## Links * Website: [https://friendi.ca](https://friendi.ca) * Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) @@ -68,7 +65,7 @@ * Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) * Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) -**Über** +## Über * [Server Information](friendica) * [Nutzungsbedingungen](tos) diff --git a/doc/de/message-flow.md b/doc/de/spec/protocol/message-flow.md similarity index 100% rename from doc/de/message-flow.md rename to doc/de/spec/protocol/message-flow.md diff --git a/doc/de/account-basics.md b/doc/de/user/account-basics.md similarity index 100% rename from doc/de/account-basics.md rename to doc/de/user/account-basics.md diff --git a/doc/de/bbcode.md b/doc/de/user/bbcode.md similarity index 100% rename from doc/de/bbcode.md rename to doc/de/user/bbcode.md diff --git a/doc/de/bugs-and-issues.md b/doc/de/user/bugs-and-issues.md similarity index 100% rename from doc/de/bugs-and-issues.md rename to doc/de/user/bugs-and-issues.md diff --git a/doc/de/channels.md b/doc/de/user/channels.md similarity index 100% rename from doc/de/channels.md rename to doc/de/user/channels.md diff --git a/doc/de/chats.md b/doc/de/user/chats.md similarity index 100% rename from doc/de/chats.md rename to doc/de/user/chats.md diff --git a/doc/de/circles-and-privacy.md b/doc/de/user/circles-and-privacy.md similarity index 100% rename from doc/de/circles-and-privacy.md rename to doc/de/user/circles-and-privacy.md diff --git a/doc/de/connectors.md b/doc/de/user/connectors.md similarity index 100% rename from doc/de/connectors.md rename to doc/de/user/connectors.md diff --git a/doc/de/events.md b/doc/de/user/events.md similarity index 100% rename from doc/de/events.md rename to doc/de/user/events.md diff --git a/doc/de/export-import-contacts.md b/doc/de/user/export-import-contacts.md similarity index 100% rename from doc/de/export-import-contacts.md rename to doc/de/user/export-import-contacts.md diff --git a/doc/de/faq.md b/doc/de/user/faq.md similarity index 99% rename from doc/de/faq.md rename to doc/de/user/faq.md index ce477b2f59..b423681bc0 100644 --- a/doc/de/faq.md +++ b/doc/de/user/faq.md @@ -2,6 +2,8 @@ * [Zur Startseite der Hilfe](help) + + * **[Wo finde ich Hilfe?](help/faq#help)** * **[Warum erhalte ich Warnungen über fehlende Zertifikate?](help/faq#ssl)** * **[Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen?](help/faq#upload)** diff --git a/doc/de/groups.md b/doc/de/user/groups.md similarity index 100% rename from doc/de/groups.md rename to doc/de/user/groups.md diff --git a/doc/de/making-friends.md b/doc/de/user/making-friends.md similarity index 100% rename from doc/de/making-friends.md rename to doc/de/user/making-friends.md diff --git a/doc/de/move-account.md b/doc/de/user/move-account.md similarity index 100% rename from doc/de/move-account.md rename to doc/de/user/move-account.md diff --git a/doc/de/quick-start/finally.md b/doc/de/user/quick-start/finally.md similarity index 85% rename from doc/de/quick-start/finally.md rename to doc/de/user/quick-start/finally.md index 7d5c94cccd..6863417f50 100644 --- a/doc/de/quick-start/finally.md +++ b/doc/de/user/quick-start/finally.md @@ -10,5 +10,5 @@ Hier sind noch einige weitere Dinge, die Dir den Start vereinfachen können. **Dokumentation** -- [Zu weiteren Netzwerken verbinden](help/connectors) +- [Zu weiteren Netzwerken verbinden](help/user/connectors) - [Zur Startseite der Hilfe](help) diff --git a/doc/de/quick-start/groups-and-pages.md b/doc/de/user/quick-start/groups-and-pages.md similarity index 96% rename from doc/de/quick-start/groups-and-pages.md rename to doc/de/user/quick-start/groups-and-pages.md index 825349cdd2..c5a9951055 100644 --- a/doc/de/quick-start/groups-and-pages.md +++ b/doc/de/user/quick-start/groups-and-pages.md @@ -18,6 +18,6 @@ Suche Dir einfach eine Gruppe und füge sie so hinzu, wie Du auch normale Freund Es gibt eine Menge Gruppen. Solltest Du beim Stöbern durch die vielen Gruppen nicht wieder hierher zurück finden, so nutze einfach den Link oben auf dieser Seite. -Wenn Du einige Gruppen hinzugefügt hast, gehe [weiter zum nächsten Schritt](help/quick-start/finally). +Wenn Du einige Gruppen hinzugefügt hast, gehe [weiter zum nächsten Schritt](help/user/quick-start/finally). diff --git a/doc/de/quick-start/guide.md b/doc/de/user/quick-start/guide.md similarity index 97% rename from doc/de/quick-start/guide.md rename to doc/de/user/quick-start/guide.md index f72a6b05d4..a6cdf98f74 100644 --- a/doc/de/quick-start/guide.md +++ b/doc/de/user/quick-start/guide.md @@ -28,6 +28,6 @@ Auch wenn Du Deinen Server so konfiguriert hast, dass der Zugriff von außerhalb -Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den ["Netzwerk"-Tab](help/quick-start/network) an. +Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den ["Netzwerk"-Tab](help/user/quick-start/network) an. diff --git a/doc/de/quick-start/making-new-friends.md b/doc/de/user/quick-start/making-new-friends.md similarity index 91% rename from doc/de/quick-start/making-new-friends.md rename to doc/de/user/quick-start/making-new-friends.md index 166f0201bc..9f295143f6 100644 --- a/doc/de/quick-start/making-new-friends.md +++ b/doc/de/user/quick-start/making-new-friends.md @@ -3,7 +3,7 @@ * [Zur Startseite der Hilfe](help) Hier siehst Du die Kontaktvorschläge. -Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/quick-start/making-new-friends) und wieder hierher kommen. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/user/quick-start/making-new-friends) und wieder hierher kommen. Diese Seite funktioniert in etwa wie die Seite für Kontaktvorschläge in Facebook. Jeder auf dieser Liste hat zugestimmt, als Kontaktvorschlag zu erscheinen. @@ -20,6 +20,6 @@ Jetzt, nachdem Du jemanden hinzugefügt hast, weißt Du vielleicht nicht mehr, w Klicke einfach auf den Link oben auf dieser Seite und Du gelangst zur Seite mit den Kontaktvorschlägen zurück, um weitere Personen hinzuzufügen. Du willst nicht einfach Personen hinzufügen, die du nicht kennst? -Kein Problem - an dieser Stelle kommen wir zu den [Gruppen und Seiten](help/quick-start/groups-and-pages). +Kein Problem - an dieser Stelle kommen wir zu den [Gruppen und Seiten](help/user/quick-start/groups-and-pages). diff --git a/doc/de/quick-start/network.md b/doc/de/user/quick-start/network.md similarity index 90% rename from doc/de/quick-start/network.md rename to doc/de/user/quick-start/network.md index a77fbe498d..78a7a4a845 100644 --- a/doc/de/quick-start/network.md +++ b/doc/de/user/quick-start/network.md @@ -3,7 +3,7 @@ * [Zur Startseite der Hilfe](help) Dies ist Dein "Netzwerk"-Tab. -Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/quick-start/network), um wieder hierher zu kommen. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/user/quick-start/network), um wieder hierher zu kommen. Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. @@ -12,6 +12,6 @@ Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträg Du kannst ihre Beiträge von hier aus kommentieren, mitteilen, dass Du den Beitrag magst oder ablehnst (Daumen hoch, Daumen runter) oder die Profile durch einen Klick auf deren Namen besuchen und dort auf deren "Pinnwand" ("Wall") Nachrichten schreiben. Nun wollen wir diese Seite mit Inhalt füllen. -Der erste Schritt ist es, [Leute zu Deinem Account hinzuzufügen](help/quick-start/making-new-friends). +Der erste Schritt ist es, [Leute zu Deinem Account hinzuzufügen](help/user/quick-start/making-new-friends). diff --git a/doc/de/remove-account.md b/doc/de/user/remove-account.md similarity index 100% rename from doc/de/remove-account.md rename to doc/de/user/remove-account.md diff --git a/doc/de/tags-and-mentions.md b/doc/de/user/tags-and-mentions.md similarity index 100% rename from doc/de/tags-and-mentions.md rename to doc/de/user/tags-and-mentions.md diff --git a/doc/de/text-comment.md b/doc/de/user/text-comment.md similarity index 100% rename from doc/de/text-comment.md rename to doc/de/user/text-comment.md diff --git a/doc/de/text-editor.md b/doc/de/user/text-editor.md similarity index 100% rename from doc/de/text-editor.md rename to doc/de/user/text-editor.md diff --git a/doc/config.md b/doc/en/admin/config.md similarity index 100% rename from doc/config.md rename to doc/en/admin/config.md diff --git a/doc/faq-admin.md b/doc/en/admin/faq.md similarity index 91% rename from doc/faq-admin.md rename to doc/en/admin/faq.md index d4553bdf66..8481c26ada 100644 --- a/doc/faq-admin.md +++ b/doc/en/admin/faq.md @@ -2,11 +2,13 @@ * [Home](help) -* **[Can I configure multiple domains with the same code instance?](help/faq-admin#multiple)** -* **[Where can I find the source code of friendica, addons and themes?](help/faq-admin#sources)** -* **[I've changed the my email address now the admin panel is gone?](help/faq-admin#adminaccount1)** -* **[Can there be more then just one admin for a node?](help/faq-admin#adminaccount2)** -* **[The Database structure seems not to be updated. What can I do?](help/faq-admin#dbupdate)** + + +* **[Can I configure multiple domains with the same code instance?](help/faq#multiple)** +* **[Where can I find the source code of friendica, addons and themes?](help/faq#sources)** +* **[I've changed the my email address now the admin panel is gone?](help/faq#adminaccount1)** +* **[Can there be more then just one admin for a node?](help/faq#adminaccount2)** +* **[The Database structure seems not to be updated. What can I do?](help/faq#dbupdate)** diff --git a/doc/improve-performance.md b/doc/en/admin/improve-performance.md similarity index 100% rename from doc/improve-performance.md rename to doc/en/admin/improve-performance.md diff --git a/doc/install-ejabberd.md b/doc/en/admin/install-ejabberd.md similarity index 100% rename from doc/install-ejabberd.md rename to doc/en/admin/install-ejabberd.md diff --git a/doc/install.md b/doc/en/admin/install.md similarity index 99% rename from doc/install.md rename to doc/en/admin/install.md index ae454ef75c..a2d841380a 100644 --- a/doc/install.md +++ b/doc/en/admin/install.md @@ -325,7 +325,7 @@ This could be achieved by a cronjob. ### (RECOMMENDED) Logging & Log Rotation At this point it is recommended that you set up logging and logrotation. -To do so please visit [Settings](help/settings) and search the 'Logs' section for more information. +To do so please visit [Settings](help/admin/settings) and search the 'Logs' section for more information. ### (RECOMMENDED) Set up a backup plan diff --git a/doc/installing-connectors.md b/doc/en/admin/installing-connectors.md similarity index 100% rename from doc/installing-connectors.md rename to doc/en/admin/installing-connectors.md diff --git a/doc/migrate.md b/doc/en/admin/migrate.md similarity index 100% rename from doc/migrate.md rename to doc/en/admin/migrate.md diff --git a/doc/settings.md b/doc/en/admin/settings.md similarity index 98% rename from doc/settings.md rename to doc/en/admin/settings.md index e28c9e37c6..d2ad192f3d 100644 --- a/doc/settings.md +++ b/doc/en/admin/settings.md @@ -48,7 +48,7 @@ It is used as fall back setting should Friendica fail to recognize the visitors The Friendica community offers some translations. Some more complete then others. -See [this help page](/help/translations) for more information about the translation process. +See [this help page](/help/developer/translations) for more information about the translation process. #### System Theme @@ -73,7 +73,7 @@ You can chose between the following modes: ##### Invitation based registry Additionally to the setting in the admin panel, you can decide if registrations are only possible using an invitation code or not. -To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/config) file. +To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/admin/config) file. If you want to use this method, the registration policy has to be set to either *open* or *requires approval*. #### Check Display Names @@ -113,7 +113,7 @@ If you use those, please refer to the documentation of those addons for further Default value is 'Database (legacy)': it's the legacy way used to store data directly in database. -Existing data can be moved to the current active backend using the ['storage move' console command](help/tools) +Existing data can be moved to the current active backend using the ['storage move' console command](help/admin/tools) If selected backend has configurable options, new fields are shown here. @@ -428,4 +428,4 @@ Say you have a subdirectory for tests and put Friendica into a further subdirect ## Other exceptions -Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/config) section of the documentation. +Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/admin/config) section of the documentation. diff --git a/doc/ssl.md b/doc/en/admin/ssl.md similarity index 100% rename from doc/ssl.md rename to doc/en/admin/ssl.md diff --git a/doc/stats.md b/doc/en/admin/stats.md similarity index 100% rename from doc/stats.md rename to doc/en/admin/stats.md diff --git a/doc/tools.md b/doc/en/admin/tools.md similarity index 100% rename from doc/tools.md rename to doc/en/admin/tools.md diff --git a/doc/update.md b/doc/en/admin/update.md similarity index 100% rename from doc/update.md rename to doc/en/admin/update.md diff --git a/doc/addons.md b/doc/en/developer/addon-development.md similarity index 100% rename from doc/addons.md rename to doc/en/developer/addon-development.md diff --git a/doc/addon-storage-backend.md b/doc/en/developer/addon-storage-backend.md similarity index 100% rename from doc/addon-storage-backend.md rename to doc/en/developer/addon-storage-backend.md diff --git a/doc/autoloader.md b/doc/en/developer/autoloader.md similarity index 96% rename from doc/autoloader.md rename to doc/en/developer/autoloader.md index 7ecb15b6c3..9cb003dc9f 100644 --- a/doc/autoloader.md +++ b/doc/en/developer/autoloader.md @@ -1,13 +1,13 @@ # Autoloader with Composer * [Home](help) - * [Developer Intro](help/developers-intro) + * [Developer Intro](help/developer/index) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application. -* [Using Composer](help/composer) +* [Using Composer](help/developer/composer) ## A quick introduction to class auto-loading @@ -197,5 +197,5 @@ So you can think of namespaces as folders in a Unix file system, with global sco ## Related -* [Using Composer](help/composer) -* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) +* [Using Composer](help/developer/composer) +* [How To Move Classes to `src`](help/developer/how-to-move-classes-to-src) diff --git a/doc/composer.md b/doc/en/developer/composer.md similarity index 93% rename from doc/composer.md rename to doc/en/developer/composer.md index 89bc8fb2d0..0465dc4981 100644 --- a/doc/composer.md +++ b/doc/en/developer/composer.md @@ -1,13 +1,13 @@ # Using Composer * [Home](help) - * [Developer Intro](help/developers-intro) + * [Developer Intro](help/developer/index) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application. -* [Class autoloading](help/autoloader) +* [Class autoloading](help/developer/autoloader) ## How to use Composer @@ -54,7 +54,7 @@ If you don't need to use any third-party library, then you don't need to use Com #### Adding a third-party library to Friendica -Does your shiny new [Addon](help/addons) need to rely on a third-party library not required by Friendica yet? +Does your shiny new [Addon](help/developer/addon-development) need to rely on a third-party library not required by Friendica yet? First, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. This file is the configuration of Friendica for Composer. It lists details about the Friendica project, but also a list of required dependencies and their target version. @@ -115,5 +115,5 @@ $> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] bin/composer.phar [mode] ## Related -* [Class autoloading](help/autoloader) -* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) +* [Class autoloading](help/developer/autoloader) +* [How To Move Classes to `src`](help/developer/developer-how-to-move-classes-to-src) diff --git a/doc/developer-domain-driven-design.md b/doc/en/developer/domain-driven-design.md similarity index 100% rename from doc/developer-domain-driven-design.md rename to doc/en/developer/domain-driven-design.md diff --git a/doc/github.md b/doc/en/developer/github.md similarity index 97% rename from doc/github.md rename to doc/en/developer/github.md index c9f4314726..4f71e8c830 100644 --- a/doc/github.md +++ b/doc/en/developer/github.md @@ -67,5 +67,5 @@ There is a console command called *typo* for this. php bin/console.php typo ``` -Check out how to work with [our Vagrant](help/vagrant) to save a lot of setup time! +Check out how to work with [our Vagrant](help/developer/vagrant) to save a lot of setup time! diff --git a/doc/developer-how-to-move-classes-to-src.md b/doc/en/developer/how-to-move-classes-to-src.md similarity index 93% rename from doc/developer-how-to-move-classes-to-src.md rename to doc/en/developer/how-to-move-classes-to-src.md index bbb9c6dfa6..a6cfe30783 100644 --- a/doc/developer-how-to-move-classes-to-src.md +++ b/doc/en/developer/how-to-move-classes-to-src.md @@ -1,10 +1,10 @@ # How To Move Classes to `src` * [Home](help) - * [Developer Intro](help/developers-intro) + * [Developer Intro](help/developer/index) -Friendica uses [Composer](help/composer) to manage autoloading. -This means that all the PHP class files moved to the `src` folder will be [automatically included](help/autoloader) when the class it defines is first used in the flow. +Friendica uses [Composer](help/developer/composer) to manage autoloading. +This means that all the PHP class files moved to the `src` folder will be [automatically included](help/developer/autoloader) when the class it defines is first used in the flow. This is an improvement over the current `require` usage since files will be included on an actual usage basis instead of the presence of a `require` call. However, there are a significant number of items to check when moving a class file from the `include` folder to the `src` folder, and this page is there to list them. @@ -103,5 +103,5 @@ Most of the time it's used for debugging purposes but there can be instances whe ## Related -* [Class autoloading](help/autoloader) -* [Using Composer](help/composer) +* [Class autoloading](help/developer/autoloader) +* [Using Composer](help/developer/composer) diff --git a/doc/developers-intro.md b/doc/en/developer/index.md similarity index 97% rename from doc/developers-intro.md rename to doc/en/developer/index.md index c4a1533a4c..8b815fb2f0 100644 --- a/doc/developers-intro.md +++ b/doc/en/developer/index.md @@ -25,7 +25,7 @@ Welcome them, answer their questions, point them to documentation or ping other ## Translation -The documentation contains help on how to translate Friendica [at Transifex](/help/translations) where the UI is translated. +The documentation contains help on how to translate Friendica [at Transifex](/help/developer/translations) where the UI is translated. If you don't want to translate the UI, or it is already done to your satisfaction, you might want to work on the translation of the /help files? ## Design @@ -41,7 +41,7 @@ If you have seen Friendica you probably have ideas to improve it, haven't you? ## Programming -Friendica uses an implementation of [Domain-Driven-Design](help/developer-domain-driven-design), please make sure to check out the provided links for hints at the expected code architecture. +Friendica uses an implementation of [Domain-Driven-Design](help/developer/domain-driven-design), please make sure to check out the provided links for hints at the expected code architecture. ### Composer @@ -66,9 +66,9 @@ If you want to have git automatically update the dependencies with composer, you just place it into `.git/hooks/post-merge` and make it executable. -* [Class autoloading](help/autoloader) -* [Using Composer](help/composer) -* [How To Move Classes to `src`](help/developer-how-to-move-classes-to-src) +* [Class autoloading](help/developer/autoloader) +* [Using Composer](help/developer/composer) +* [How To Move Classes to `src`](help/developer/how-to-move-classes-to-src) ### Coding standards @@ -148,7 +148,7 @@ If you want to get involved here: ### Client software -As Friendica is using a [Twitter/GNU Social compatible API](help/api) any of the clients for those platforms should work with Friendica as well. +As Friendica is using a [Twitter/GNU Social compatible API](help/spec/api/index) any of the clients for those platforms should work with Friendica as well. Furthermore, there are several client projects, especially for use with Friendica. If you are interested in improving those clients, please contact the developers of the clients directly. diff --git a/doc/smarty3-templates.md b/doc/en/developer/smarty3-templates.md similarity index 100% rename from doc/smarty3-templates.md rename to doc/en/developer/smarty3-templates.md diff --git a/doc/strategy-hooks.md b/doc/en/developer/strategy-hooks.md similarity index 100% rename from doc/strategy-hooks.md rename to doc/en/developer/strategy-hooks.md diff --git a/doc/tests.md b/doc/en/developer/tests.md similarity index 100% rename from doc/tests.md rename to doc/en/developer/tests.md diff --git a/doc/themes.md b/doc/en/developer/themes.md similarity index 100% rename from doc/themes.md rename to doc/en/developer/themes.md diff --git a/doc/translations.md b/doc/en/developer/translations.md similarity index 100% rename from doc/translations.md rename to doc/en/developer/translations.md diff --git a/doc/vagrant.md b/doc/en/developer/vagrant.md similarity index 100% rename from doc/vagrant.md rename to doc/en/developer/vagrant.md diff --git a/doc/en/home.md b/doc/en/home.md new file mode 100644 index 0000000000..0d517edd53 --- /dev/null +++ b/doc/en/home.md @@ -0,0 +1,80 @@ +# Help + +## User Manual + +* General functions - first steps + * [Account Basics](help/user/account-basics) + * [New User Quick Start](help/user/quick-start/guide) + * [Creating posts](help/user/text-editor) + * [BBCode tag reference](help/user/bbcode) + * [Comment, sort and delete posts](help/user/text-comment) + * [Accesskey reference](help/user/access-keys) + * [Events](help/user/events) +* You and other users + * [Connectors](help/user/connectors) + * [Making Friends](help/user/making-friends) + * [Safety](help/user/safety) + * [Circles and Privacy](help/user/circles-and-privacy) + * [Tags and Mentions](help/user/tags-and-mentions) + * [Groups](help/user/groups) + * [Channels](help/user/channels) + * [Chats](help/user/chats) +* Further information + * [Frequently asked questions (FAQ)](help/user/faq) + * [Move your account](help/user/move-account) + * [Export / Import of followed Contacts](help/user/export-import-contacts) + * [Delete your account](help/user/remove-account) + * [Bugs and Issues](help/user/bugs-and-issues) + +## Admin Manual + +* [Frequently asked questions (FAQ)](help/admin/faq) +* [Installation](help/admin/install) +* [Updating](help/admin/update) +* [Settings & Admin Panel](help/admin/settings) +* [Installing Connectors](help/admin/installing-connectors) +* [Installing an ejabberd server (XMPP chat) with synchronized credentials](help/admin/install-ejabberd) +* [Using SSL with Friendica](help/admin/ssl) +* [Config values that can only be set in config/local.config.php](help/admin/config) +* [Improving Performance](help/admin/improve-performance) +* [Migrating to a new server](help/admin/migrate) +* [Administration Tools](help/admin/tools) + +## Developer Manual + +* [Get started](help/developer/index) +* Set up development environment + * [On GitHub](help/developer/github) + * [On Vagrant](help/developer/vagrant) +* Code structure + * [Domain-Driven-Design](help/developer/domain-driven-design) + * [Addon Development](help/developer/addons) + * [Theme Development](help/developer/themes) + * [Smarty 3 Templates](help/developer/smarty3-templates) + * [Storage backend addon](help/developer/addon-storage-backend) +* How To + * [Translate Friendica](help/developer/translations) + * [Using Composer](help/developer/composer) + * [Move classes to `src`](help/developer/how-to-move-classes-to-src) + * [Run tests](help/developer/tests) +* Reference + * [API endpoints](help/spec/api/index) + * [Code (Doxygen generated - sets cookies)](doc/html/) + * [Protocol Documentation](help/spec/protocol/protocol) + * [Database schema documentation](help/database) + * [Class Autoloading](help/developer/autoloader) + +## Links + +* Website: [https://friendi.ca](https://friendi.ca) +* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) +* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) +* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) +* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) +* Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) + +## About + +* [Server Information](friendica) +* [Terms of Service](tos) +* [Credits](credits) diff --git a/doc/api-entities.md b/doc/en/spec/api/entities.md similarity index 93% rename from doc/api-entities.md rename to doc/en/spec/api/entities.md index 4e4512e7dc..2b895494cd 100644 --- a/doc/api-entities.md +++ b/doc/en/spec/api/entities.md @@ -18,31 +18,31 @@ like -List of Contacts +List of Contacts No dislike -List of Contacts +List of Contacts No attendyes -List of Contacts +List of Contacts No attendno -List of Contacts +List of Contacts No attendmaybe -List of Contacts +List of Contacts No @@ -330,31 +330,31 @@ Ex: Wed May 23 06:01:13 +0000 2007 hashtags -List of Hashtags +List of Hashtags No symbols -List of Symbols +List of Symbols No urls -List of URLs +List of URLs No user_mentions -List of User mentions +List of User mentions No media -List of Medias +List of Medias No @@ -570,13 +570,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 user -Contact +Contact No friendica_author -Contact +Contact No @@ -584,7 +584,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_owner -Contact +Contact No @@ -614,7 +614,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_activities -Activities +Activities No @@ -632,13 +632,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 attachments -List of Attachments +List of Attachments Yes entities -Entities +Entities Yes @@ -721,7 +721,7 @@ Identical to [the Twitter Media Object](https://developer.twitter.com/en/docs/tw sizes -Sizes +Sizes No @@ -1036,13 +1036,13 @@ Mutually exclusive with link. friendica_activities -Activities +Activities friendica_comments -List of Items +List of Items @@ -1260,13 +1260,13 @@ Mutually exclusive with link. sender -Contact +Contact recipient -Contact +Contact @@ -1471,25 +1471,25 @@ Mutually exclusive with link. medium -Size +Size No large -Size +Size Yes thumb -Size +Size Yes small -Size +Size Yes diff --git a/doc/api-friendica.md b/doc/en/spec/api/friendica.md similarity index 94% rename from doc/api-friendica.md rename to doc/en/spec/api/friendica.md index 59157c8aaf..471e28f2a2 100644 --- a/doc/api-friendica.md +++ b/doc/en/spec/api/friendica.md @@ -1,7 +1,7 @@ # Friendica API * [Home](help) - * [Using the APIs](help/api) + * [Using the APIs](help/spec/api/index) ## Overview @@ -11,13 +11,13 @@ Authentication is the same as described in [Using the APIs](help/api#authenticat ## Entities -These endpoints uses the [Friendica API entities](help/api-entities). +These endpoints uses the [Friendica API entities](help/spec/api/entities). ## Endpoints ### GET api/friendica/events -Returns a list of [Event](help/api-entities#event) entities for the current logged in user. +Returns a list of [Event](help/spec/api/entities#event) entities for the current logged in user. #### Parameters @@ -52,7 +52,7 @@ Delete event from calendar (not the message) ### GET api/externalprofile/show -Returns a [Contact](help/api-entities#contact) entity for the provided profile URL. +Returns a [Contact](help/spec/api/entities#contact) entity for the provided profile URL. #### Parameters @@ -60,7 +60,7 @@ Returns a [Contact](help/api-entities#contact) entity for the provided profile U ### GET api/statuses/public_timeline -Returns a list of public [Items](help/api-entities#item) posted on this node. +Returns a list of public [Items](help/spec/api/entities#item) posted on this node. Equivalent of the local community page. #### Parameters @@ -79,7 +79,7 @@ Equivalent of the local community page. ### GET api/statuses/networkpublic_timeline -Returns a list of public [Items](help/api-entities#item) this node is aware of. +Returns a list of public [Items](help/spec/api/entities#item) this node is aware of. Equivalent of the global community page. #### Parameters @@ -206,7 +206,7 @@ Deprecated Twitter received direct message list endpoint. ### GET api/direct_messages/all -Returns all [Private Messages](help/api-entities#private+message). +Returns all [Private Messages](help/spec/api/entities#private+message). #### Parameters @@ -219,7 +219,7 @@ Returns all [Private Messages](help/api-entities#private+message). ### GET api/direct_messages/conversation -Returns all replies of a single private message conversation. Returns [Private Messages](help/api-entities#private+message) +Returns all replies of a single private message conversation. Returns [Private Messages](help/spec/api/entities#private+message) #### Parameters @@ -233,7 +233,7 @@ Returns all replies of a single private message conversation. Returns [Private M ### GET api/direct_messages/sent -Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/api-entities#private+message). +Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/spec/api/entities#private+message). #### Parameters @@ -300,7 +300,7 @@ On error: ### GET api/friendica/direct_messages_search (GET; AUTH) -Returns [Private Messages](help/api-entities#private+message) matching the provided search string. +Returns [Private Messages](help/spec/api/entities#private+message) matching the provided search string. #### Parameters @@ -339,7 +339,7 @@ Array of: * `name`: name of the circle * `gid`: id of the circle -* `user`: array of [Contacts](help/api-entities#contact) +* `user`: array of [Contacts](help/spec/api/entities#contact) ### POST api/friendica/circle_create @@ -357,7 +357,7 @@ JSON data as Array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/api-entities#contact) +* List of [Contacts](help/spec/api/entities#contact) #### Return values @@ -386,7 +386,7 @@ JSON data as array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/api-entities#contact) +* List of [Contacts](help/spec/api/entities#contact) #### Return values @@ -423,7 +423,7 @@ Array of: ### GET api/friendica/notifications -Return last 50 [Notifications](help/api-entities#notification) for the current user, ordered by date with unseen item on top. +Return last 50 [Notifications](help/spec/api/entities#notification) for the current user, ordered by date with unseen item on top. #### Parameters @@ -439,7 +439,7 @@ Set notification as seen. #### Return values -If the note is linked to an item, returns an [Item](help/api-entities#item). +If the note is linked to an item, returns an [Item](help/spec/api/entities#item). Otherwise, a success status is returned: @@ -449,7 +449,7 @@ Otherwise, a success status is returned: ### GET api/friendica/photo -Returns a [Photo](help/api-entities#photo). +Returns a [Photo](help/spec/api/entities#photo). #### Parameters @@ -523,7 +523,7 @@ xml: ### GET api/friendica/photos/list -Returns the API user's [Photo List Items](help/api-entities#photo+list+item). +Returns the API user's [Photo List Items](help/spec/api/entities#photo+list+item). #### Return values @@ -772,7 +772,7 @@ On success: ### GET api/friendica/profile/show -Returns the [Profile](help/api-entities#profile) data of the authenticated user. +Returns the [Profile](help/spec/api/entities#profile) data of the authenticated user. #### Return values diff --git a/doc/api-gnu-social.md b/doc/en/spec/api/gnu-social.md similarity index 92% rename from doc/api-gnu-social.md rename to doc/en/spec/api/gnu-social.md index b41a3c4e7b..aeb8e53a2c 100644 --- a/doc/api-gnu-social.md +++ b/doc/en/spec/api/gnu-social.md @@ -1,17 +1,17 @@ # GNU Social API * [Home](help) - * [Using the APIs](help/api) + * [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in [the official GNU Social Twitter-like API reference](https://gnusocial.net/doc/twitterapi). -Authentication is the same as described in [Using the APIs](help/api#authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Entities -These endpoints use the [Friendica API entities](help/api-entities). +These endpoints use the [Friendica API entities](help/spec/api/entities). ## Implemented endpoints diff --git a/doc/api.md b/doc/en/spec/api/index.md similarity index 100% rename from doc/api.md rename to doc/en/spec/api/index.md diff --git a/doc/api-mastodon.md b/doc/en/spec/api/mastodon.md similarity index 99% rename from doc/api-mastodon.md rename to doc/en/spec/api/mastodon.md index 65fc5da1b5..eb33c9ceb4 100644 --- a/doc/api-mastodon.md +++ b/doc/en/spec/api/mastodon.md @@ -1,17 +1,17 @@ # Mastodon API * [Home](help) - * [Using the APIs](help/api) + * [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in [the official Mastodon API reference](https://docs.joinmastodon.org/api/). -Authentication is the same as described in [Using the APIs](help/api#authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Clients -Please find a list of supported apps at [FAQ](help/faq#clients). +Please find a list of supported apps at [FAQ](help/user/faq#clients). ## Entities diff --git a/doc/api-twitter.md b/doc/en/spec/api/twitter.md similarity index 99% rename from doc/api-twitter.md rename to doc/en/spec/api/twitter.md index 3a3832b6b2..f45c2434a8 100644 --- a/doc/api-twitter.md +++ b/doc/en/spec/api/twitter.md @@ -1,17 +1,17 @@ # Twitter API * [Home](help) - * [Using the APIs](help/api) + * [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in the [official Twitter API reference](https://developer.twitter.com/en/docs/api-reference-index). -Authentication is the same as described in [Using the APIs](help/api#authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Entities -These endpoints use the [Friendica API entities](help/api-entities). +These endpoints use the [Friendica API entities](help/spec/api/entities). ## Different behaviour diff --git a/doc/message-flow.md b/doc/en/spec/message-flow.md similarity index 100% rename from doc/message-flow.md rename to doc/en/spec/message-flow.md diff --git a/doc/spec/protocol/dfrn-snap2.jpg b/doc/en/spec/protocol/dfrn-snap2.jpg similarity index 100% rename from doc/spec/protocol/dfrn-snap2.jpg rename to doc/en/spec/protocol/dfrn-snap2.jpg diff --git a/doc/spec/protocol/dfrn2.odt b/doc/en/spec/protocol/dfrn2.odt similarity index 100% rename from doc/spec/protocol/dfrn2.odt rename to doc/en/spec/protocol/dfrn2.odt diff --git a/doc/spec/protocol/dfrn2.pdf b/doc/en/spec/protocol/dfrn2.pdf similarity index 100% rename from doc/spec/protocol/dfrn2.pdf rename to doc/en/spec/protocol/dfrn2.pdf diff --git a/doc/spec/protocol/dfrn2_contact_confirmation.png b/doc/en/spec/protocol/dfrn2_contact_confirmation.png similarity index 100% rename from doc/spec/protocol/dfrn2_contact_confirmation.png rename to doc/en/spec/protocol/dfrn2_contact_confirmation.png diff --git a/doc/spec/protocol/dfrn2_contact_confirmation.svg b/doc/en/spec/protocol/dfrn2_contact_confirmation.svg similarity index 100% rename from doc/spec/protocol/dfrn2_contact_confirmation.svg rename to doc/en/spec/protocol/dfrn2_contact_confirmation.svg diff --git a/doc/spec/protocol/dfrn2_contact_request.png b/doc/en/spec/protocol/dfrn2_contact_request.png similarity index 100% rename from doc/spec/protocol/dfrn2_contact_request.png rename to doc/en/spec/protocol/dfrn2_contact_request.png diff --git a/doc/spec/protocol/dfrn2_contact_request.svg b/doc/en/spec/protocol/dfrn2_contact_request.svg similarity index 100% rename from doc/spec/protocol/dfrn2_contact_request.svg rename to doc/en/spec/protocol/dfrn2_contact_request.svg diff --git a/doc/protocol.md b/doc/en/spec/protocol/protocol.md similarity index 93% rename from doc/protocol.md rename to doc/en/spec/protocol/protocol.md index 2580c0f9fd..07ead3aeeb 100644 --- a/doc/protocol.md +++ b/doc/en/spec/protocol/protocol.md @@ -7,7 +7,7 @@ * [Document with the DFRN specification](spec/dfrn2.pdf) * [Schema of the contact request process](spec/dfrn2_contact_request.png) * [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png) -* [Description of the message flow](help/message-flow) +* [Description of the message flow](help/spec/message-flow) ## ActivityStreams diff --git a/doc/spec/protocol/zot-2012.txt b/doc/en/spec/protocol/zot-2012.txt similarity index 100% rename from doc/spec/protocol/zot-2012.txt rename to doc/en/spec/protocol/zot-2012.txt diff --git a/doc/spec/protocol/zot.txt b/doc/en/spec/protocol/zot.txt similarity index 100% rename from doc/spec/protocol/zot.txt rename to doc/en/spec/protocol/zot.txt diff --git a/doc/access-keys.md b/doc/en/user/access-keys.md similarity index 100% rename from doc/access-keys.md rename to doc/en/user/access-keys.md diff --git a/doc/account-basics.md b/doc/en/user/account-basics.md similarity index 100% rename from doc/account-basics.md rename to doc/en/user/account-basics.md diff --git a/doc/bbcode.md b/doc/en/user/bbcode.md similarity index 99% rename from doc/bbcode.md rename to doc/en/user/bbcode.md index 629fc86a7e..6aec790d62 100644 --- a/doc/bbcode.md +++ b/doc/en/user/bbcode.md @@ -1,6 +1,6 @@ # Friendica BBCode tags reference -* [Creating posts](help/text-editor) +* [Creating posts](help/user/text-editor) ## Inline diff --git a/doc/bugs-and-issues.md b/doc/en/user/bugs-and-issues.md similarity index 100% rename from doc/bugs-and-issues.md rename to doc/en/user/bugs-and-issues.md diff --git a/doc/channels.md b/doc/en/user/channels.md similarity index 100% rename from doc/channels.md rename to doc/en/user/channels.md diff --git a/doc/chats.md b/doc/en/user/chats.md similarity index 100% rename from doc/chats.md rename to doc/en/user/chats.md diff --git a/doc/circles-and-privacy.md b/doc/en/user/circles-and-privacy.md similarity index 100% rename from doc/circles-and-privacy.md rename to doc/en/user/circles-and-privacy.md diff --git a/doc/connectors.md b/doc/en/user/connectors.md similarity index 100% rename from doc/connectors.md rename to doc/en/user/connectors.md diff --git a/doc/events.md b/doc/en/user/events.md similarity index 100% rename from doc/events.md rename to doc/en/user/events.md diff --git a/doc/export-import-contacts.md b/doc/en/user/export-import-contacts.md similarity index 87% rename from doc/export-import-contacts.md rename to doc/en/user/export-import-contacts.md index bb8c5d00f5..3d49fd6829 100644 --- a/doc/export-import-contacts.md +++ b/doc/en/user/export-import-contacts.md @@ -2,7 +2,7 @@ * [Home](help) -In addition to [move your account](help/move-account) you can export and import the list of accounts you follow. +In addition to [move your account](help/user/move-account) you can export and import the list of accounts you follow. The exported list is stored as CSV file that is compatible to the format used by other platforms as e.g. Mastodon, Misskey or Pleroma. ## Export of followed Contacts diff --git a/doc/faq.md b/doc/en/user/faq.md similarity index 93% rename from doc/faq.md rename to doc/en/user/faq.md index 11bbf333ae..9c86d908e1 100644 --- a/doc/faq.md +++ b/doc/en/user/faq.md @@ -2,17 +2,18 @@ * [Home](help) -* **[Where I can find help?](help/faq#help)** -* **[Why do I get warnings about certificates?](help/faq#ssl)** -* **[How can I upload images, files, links, videos and sound files to posts?](help/faq#upload)** -* **[Is it possible to have different avatars per profile?](help/faq#avatars)** -* **[How can I view Friendica in a certain language?](help/faq#language)** -* **[How do blocked, ignored, archived and hidden contacts behave?](help/faq#contacts)** -* **[What happens when an account is removed? Is it truly deleted?](help/faq#removed)** -* **[Can I subscribe to a hashtag?](help/faq#hashtag)** -* **[How to create an RSS feed of the stream?](help/faq#rss)** -* **[What friendica clients can I use?](help/faq#clients)** + +* **[Where I can find help?](help/user/faq#help)** +* **[Why do I get warnings about certificates?](help/user/faq#ssl)** +* **[How can I upload images, files, links, videos and sound files to posts?](help/user/faq#upload)** +* **[Is it possible to have different avatars per profile?](help/user/faq#avatars)** +* **[How can I view Friendica in a certain language?](help/user/faq#language)** +* **[How do blocked, ignored, archived and hidden contacts behave?](help/user/faq#contacts)** +* **[What happens when an account is removed? Is it truly deleted?](help/user/faq#removed)** +* **[Can I subscribe to a hashtag?](help/user/faq#hashtag)** +* **[How to create an RSS feed of the stream?](help/user/faq#rss)** +* **[What friendica clients can I use?](help/user/faq#clients)** ## Where I can find help? @@ -42,12 +43,12 @@ These warnings can have three reasons: 2. The server has a self-signed certificate (not recommended). 3. The certificate is expired. -We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/ssl).) +We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/admin/ssl).) ## How can I upload images, files, links, videos and sound files to posts? -You can upload images from your computer using the [editor](help/text-editor). +You can upload images from your computer using the [editor](help/user/text-editor). An overview of all uploaded images is listed at *yourpage.com/profile/profilename/photos*. On that page, you can also upload images directly and choose if your contacts will receive a message about this upload. @@ -102,7 +103,7 @@ When a certain language is forced, the language remains until session is closed. ## How do blocked, ignored, archived and hidden contacts behave? These are various categories of contacts that are restricted in some way. -Many of these types are related to [Safety](help/safety). +Many of these types are related to [Safety](help/user/safety). ### Blocked @@ -173,7 +174,7 @@ Example: Friendica Support ## What friendica clients can I use? -Friendica supports [Mastodon API](help/api-mastodon) and [Twitter API | gnusocial](help/api). +Friendica supports [Mastodon API](help/spec/api/mastodon) and [Twitter API | gnusocial](help/spec/api/index). This means you can use some of the Mastodon and Twitter clients for Friendica. The available features are client specific and may differ. Clients dedicated to Friendica are marked in **bold**. diff --git a/doc/groups.md b/doc/en/user/groups.md similarity index 100% rename from doc/groups.md rename to doc/en/user/groups.md diff --git a/doc/keyboard-shortcuts.md b/doc/en/user/keyboard-shortcuts.md similarity index 100% rename from doc/keyboard-shortcuts.md rename to doc/en/user/keyboard-shortcuts.md diff --git a/doc/making-friends.md b/doc/en/user/making-friends.md similarity index 100% rename from doc/making-friends.md rename to doc/en/user/making-friends.md diff --git a/doc/move-account.md b/doc/en/user/move-account.md similarity index 100% rename from doc/move-account.md rename to doc/en/user/move-account.md diff --git a/doc/quick-start/finally.md b/doc/en/user/quick-start/finally.md similarity index 81% rename from doc/quick-start/finally.md rename to doc/en/user/quick-start/finally.md index b04fe4ad1d..8f06415552 100644 --- a/doc/quick-start/finally.md +++ b/doc/en/user/quick-start/finally.md @@ -8,5 +8,5 @@ Here are some more things to help get you started: **Documentation** -- [Connections to other networks](help/connectors) +- [Connections to other networks](help/user/connectors) - [Help index](help) diff --git a/doc/quick-start/groups-and-pages.md b/doc/en/user/quick-start/groups-and-pages.md similarity index 88% rename from doc/quick-start/groups-and-pages.md rename to doc/en/user/quick-start/groups-and-pages.md index d9c5bb6893..9f29892c9c 100644 --- a/doc/quick-start/groups-and-pages.md +++ b/doc/en/user/quick-start/groups-and-pages.md @@ -1,5 +1,5 @@ This is the global directory. -If you get lost, you can [click this link](help/quick-start/groups-and-pages) to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/groups-and-pages) to bring yourself back here. On this page, you'll find a collection of groups. Groups are not real people. @@ -13,6 +13,6 @@ Simply find a group you're interested in, and connect to it the same way you did There are a lot of groups, and you're likely to get lost. Remember the link at the top of this page will bring you back here. -Once you've added some groups, [move on to the next section](help/quick-start/finally). +Once you've added some groups, [move on to the next section](help/user/quick-start/finally). diff --git a/doc/quick-start/guide.md b/doc/en/user/quick-start/guide.md similarity index 95% rename from doc/quick-start/guide.md rename to doc/en/user/quick-start/guide.md index baa9b992a1..3d875062dd 100644 --- a/doc/quick-start/guide.md +++ b/doc/en/user/quick-start/guide.md @@ -18,6 +18,6 @@ Once you've finished writing your post, click on the padlock icon or permissions If you do not change anything, your post will be public. This means it will appear to anybody who views your profile, and in the community tab if your site has it enabled, as well as in the network tab of any of your contacts. -Play around with this a bit, then when you're ready to move on, we'll take a look at the [Network Tab](help/quick-start/network). +Play around with this a bit, then when you're ready to move on, we'll take a look at the [Network Tab](help/user/quick-start/network). diff --git a/doc/quick-start/making-new-friends.md b/doc/en/user/quick-start/making-new-friends.md similarity index 80% rename from doc/quick-start/making-new-friends.md rename to doc/en/user/quick-start/making-new-friends.md index b81f18c46c..6c26180673 100644 --- a/doc/quick-start/making-new-friends.md +++ b/doc/en/user/quick-start/making-new-friends.md @@ -1,5 +1,5 @@ This is your Suggested Friends page. -If you get lost, you can [click this link](help/quick-start/making-new-friends) to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/making-new-friends) to bring yourself back here. This is a bit like the Friend Suggestions page of Facebook. Everybody on this list has agreed that they may be suggested as a friend. @@ -14,6 +14,6 @@ Now you've added one, you're probably lost. Click the link at the top of this page to go back to the suggested friends list and add some more. Feel uncomfortable adding people you don't know? -Don't worry - that's where [Groups and Pages](help/quick-start/groups-and-pages) come in! +Don't worry - that's where [Groups and Pages](help/user/quick-start/groups-and-pages) come in! diff --git a/doc/quick-start/network.md b/doc/en/user/quick-start/network.md similarity index 79% rename from doc/quick-start/network.md rename to doc/en/user/quick-start/network.md index 0e97747d77..5159b6bdd8 100644 --- a/doc/quick-start/network.md +++ b/doc/en/user/quick-start/network.md @@ -1,5 +1,5 @@ This is your Network Tab. -If you get lost, you can [click this link](help/quick-start/network) to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/network) to bring yourself back here. This is a bit like the Newsfeed at Facebook or the Stream at Diaspora. It's where all the posts from your contacts, groups, and feeds will appear. @@ -7,6 +7,6 @@ If you're new, you won't see anything in this page, unless you posted your statu If you've already added a few friends, you'll be able to see their posts. Here, you can comment, like, or dislike posts, or click on somebody's name to visit their profile page where you can write on their wall. -Now we need to fill it up, the first step, is to [make some new friends](help/quick-start/making-new-friends). +Now we need to fill it up, the first step, is to [make some new friends](help/user/quick-start/making-new-friends). diff --git a/doc/remove-account.md b/doc/en/user/remove-account.md similarity index 100% rename from doc/remove-account.md rename to doc/en/user/remove-account.md diff --git a/doc/safety.md b/doc/en/user/safety.md similarity index 100% rename from doc/safety.md rename to doc/en/user/safety.md diff --git a/doc/tags-and-mentions.md b/doc/en/user/tags-and-mentions.md similarity index 100% rename from doc/tags-and-mentions.md rename to doc/en/user/tags-and-mentions.md diff --git a/doc/text-comment.md b/doc/en/user/text-comment.md similarity index 100% rename from doc/text-comment.md rename to doc/en/user/text-comment.md diff --git a/doc/text-editor.md b/doc/en/user/text-editor.md similarity index 100% rename from doc/text-editor.md rename to doc/en/user/text-editor.md diff --git a/doc/two-factor-authentication.md b/doc/en/user/two-factor-authentication.md similarity index 100% rename from doc/two-factor-authentication.md rename to doc/en/user/two-factor-authentication.md diff --git a/doc/home.md b/doc/home.md deleted file mode 100644 index 256f14b187..0000000000 --- a/doc/home.md +++ /dev/null @@ -1,79 +0,0 @@ -# Help - -## User Manual - -* General functions - first steps - * [Account Basics](help/account-basics) - * [New User Quick Start](help/quick-start/guide) - * [Creating posts](help/text-editor) - * [BBCode tag reference](help/bbcode) - * [Comment, sort and delete posts](help/text-comment) - * [Accesskey reference](help/access-keys) - * [Events](help/events) -* You and other users - * [Connectors](help/connectors) - * [Making Friends](help/making-friends) - * [Safety](help/safety) - * [Circles and Privacy](help/circles-and-privacy) - * [Tags and Mentions](help/tags-and-mentions) - * [Community Groups](help/groups) - * [Channels](help/channels) - * [Chats](help/chats) -* Further information - * [Move your account](help/move-account) - * [Export / Import of followed Contacts](help/export-import-contacts) - * [Delete your account](help/remove-account) - * [Frequently asked questions (FAQ)](help/faq) - -## Admin Manual - -* [Install](help/install) -* [Update](help/update) -* [Settings & Admin Panel](help/settings) -* [Installing Connectors](help/installing-connectors) -* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd) -* [Using SSL with Friendica](help/ssl) -* [Config values that can only be set in config/local.config.php](help/config) -* [Improve Performance](help/improve-performance) -* [Migrate](help/migrate) -* [Administration Tools](help/tools) -* [Admin FAQ](help/faq-admin) - -## Developer Manual - -* [Get started](help/developers-intro) -* Set up development environment - * [Help on GitHub](help/github) - * [Help on Vagrant](help/vagrant) - * [Bugs and Issues](help/bugs-and-issues) -* Code structure - * [Domain-Driven-Design](help/developer-domain-driven-design) - * [Addon Development](help/addons) - * [Theme Development](help/themes) - * [Smarty 3 Templates](help/smarty3-templates) - * [Storage backend addon](help/addon-storage-backend) -* How To - * [Translate Friendica](help/translations) - * [Use Composer](help/composer) - * [Move classes to `src`](help/developer-how-to-move-classes-to-src) - * [Run tests](help/tests) -* Reference - * [API endpoints](help/api) - * [Code (Doxygen generated - sets cookies)](doc/html/) - * [Protocol Documentation](help/protocol) - * [Database schema documentation](help/database) - * [Class Autoloading](help/autoloader) - -## Links - -* Website: [https://friendi.ca](https://friendi.ca) -* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) -* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) -* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) -* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) -* Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) -## About - -* [Server Information](friendica) -* [Terms of Service](tos) -* [Credits](credits) diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 0635b5cbee..06332b2096 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -105,7 +105,7 @@ class Summary extends BaseAdmin '%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', $well_known, $well_known, - DI::baseUrl() . '/help/install' + DI::baseUrl() . '/help/admin/install' ); } diff --git a/src/Module/Help.php b/src/Module/Help.php index f68d5d45c8..98b2aee9b5 100644 --- a/src/Module/Help.php +++ b/src/Module/Help.php @@ -42,11 +42,11 @@ class Help extends BaseModule } $title = basename($path); $filename = $path; - $text = self::loadDocFile('doc/' . $path . '.md', $lang); + $text = self::loadDocFile($path . '.md', $lang); DI::page()['title'] = DI::l10n()->t('Help:') . ' ' . str_replace('-', ' ', $title); } - $home = self::loadDocFile('doc/home.md', $lang); + $home = self::loadDocFile('home.md', $lang); if (!$text) { $text = $home; $filename = "home"; @@ -110,23 +110,25 @@ class Help extends BaseModule return $html; } - private static function loadDocFile($fileName, $lang = 'en') + private static function loadDocFile($filePath, $lang = 'en') { - $baseName = basename($fileName); - $dirName = dirname($fileName); - // An ugly hack to get the guide, which is inside a directory now, working again in German - // A non-hacky solution could be found, but if this file is being deleted soon when switching to mkdocs then...? - if (strpos($dirName, "quick-start")) { - if (file_exists("doc/$lang/quick-start/$baseName")) { - return file_get_contents("doc/$lang/quick-start/$baseName"); - } - } - if (file_exists("$dirName/$lang/$baseName")) { - return file_get_contents("$dirName/$lang/$baseName"); + $baseDir = "doc"; + + // Try loading docs inside a language dir first, then try English dir, then fall back to looking at the root dir + $docPath = "$baseDir/$lang/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); } - if (file_exists($fileName)) { - return file_get_contents($fileName); + $docPath = "$baseDir/en/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); + } + + // Delete this once database docs have been moved into en/spec/database + $docPath = "$baseDir/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); } return ''; diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php index bd1fe9accc..c58ebb6d08 100644 --- a/view/theme/vier/theme.php +++ b/view/theme/vier/theme.php @@ -218,7 +218,7 @@ function vier_community_info() $r[$index]["url"] = Contact::magicLink($helper["url"]); } - $r[] = ["url" => "help/quick-start/guide", "name" => DI::l10n()->t("Quick Start")]; + $r[] = ["url" => "help/user/quick-start/guide", "name" => DI::l10n()->t("Quick Start")]; $tpl = Renderer::getMarkupTemplate('ch_helpers.tpl'); From 00397a34b56579eb79e7510af2ff2933ef7e88bd Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 Oct 2025 05:55:45 +0000 Subject: [PATCH 014/138] Don't display additional media links when page is a media page --- src/Model/Item.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 72334e4183..d14a0f5f0c 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3034,7 +3034,7 @@ class Item if (!empty($sharedSplitAttachments)) { $s = self::addGallery($s, $sharedSplitAttachments['visual']); $s = self::addVisualAttachments($sharedSplitAttachments['visual'], $shared_item, $s, true, $uid); - $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid); + $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid, $shared_item); $s = self::addNonVisualAttachments($sharedSplitAttachments['additional'], $item, $s); $body = BBCode::removeSharedData($body); } @@ -3047,7 +3047,7 @@ class Item $s = self::addGallery($s, $itemSplitAttachments['visual']); $s = self::addVisualAttachments($itemSplitAttachments['visual'], $item, $s, false, $uid); - $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid); + $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid, $item); $s = self::addNonVisualAttachments($itemSplitAttachments['additional'], $item, $s); $s = self::addQuestions($item, $s); @@ -3359,16 +3359,18 @@ class Item * @param bool $shared * @param array $ignore_links A list of URLs to ignore * @param int $uid + * @param array $item * @return string modified content * @throws InternalServerErrorException * @throws ServiceUnavailableException */ - private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid): string + private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid, array $item): string { DI::profiler()->startRecording('rendering'); // Don't show a preview when there is a visual attachment (audio or video) - $types = $attachments['visual']->column('type'); - $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $types = $attachments['visual']->column('type'); + $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $has_media = in_array($item['post-type'] ?? null, [Item::PT_AUDIO, Item::PT_VIDEO]); /** @var ?PostMedia $attachment */ $attachment = null; @@ -3460,7 +3462,7 @@ class Item // @todo Use a template $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); - if ($preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { + if (!$has_media && $preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, $data, $uriid, $preview_mode, DI::pConfig()->get($uid, 'system', 'embed_remote_media', false)); } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { $rendered = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ From 69cb52f60e88bbcc2be0333a5764cb0d8bd59612 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 12 Oct 2025 15:37:03 +0000 Subject: [PATCH 015/138] Issue 14782: Disable private message to group --- src/Content/Item.php | 10 ++++------ src/Model/Contact.php | 7 ++++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Content/Item.php b/src/Content/Item.php index 6d116561ca..f8eee3cb2f 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -396,14 +396,12 @@ class Item $cid = 0; $pcid = $item['author-id']; - $network = ''; $rel = 0; $condition = ['uid' => $this->userSession->getLocalUserId(), 'uri-id' => $item['author-uri-id']]; - $contact = DBA::selectFirst('contact', ['id', 'network', 'rel'], $condition); + $contact = DBA::selectFirst('contact', ['id', 'network', 'rel', 'contact-type', 'protocol', 'self'], $condition); if (DBA::isResult($contact)) { - $cid = $contact['id']; - $network = $contact['network']; - $rel = $contact['rel']; + $cid = $contact['id']; + $rel = $contact['rel']; } if (!empty($pcid)) { @@ -423,7 +421,7 @@ class Item $contact_url = 'contact/' . $cid; $posts_link = $contact_url . '/posts'; - if (in_array($network, [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA])) { + if (Contact::canReceivePrivateMessages($contact)) { $pm_url = 'message/new/' . $cid; } } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index b2f9e2bd63..34bfafb251 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -3753,10 +3753,11 @@ class Contact */ public static function canReceivePrivateMessages(array $contact): bool { - $protocol = $contact['network'] ?? $contact['protocol'] ?? Protocol::PHANTOM; - $self = $contact['self'] ?? false; + $protocol = $contact['network'] ?? $contact['protocol'] ?? Protocol::PHANTOM; + $self = $contact['self'] ?? false; + $type = $contact['contact-type'] ?? Contact::TYPE_UNKNOWN; - return in_array($protocol, [Protocol::DFRN, Protocol::DIASPORA, Protocol::ACTIVITYPUB]) && !$self; + return in_array($protocol, [Protocol::DFRN, Protocol::DIASPORA, Protocol::ACTIVITYPUB]) && !$self && ($type != Contact::TYPE_COMMUNITY); } /** From 55271fcd14eb898c123afb971f27b99224667b16 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 9 Oct 2025 20:22:30 +0000 Subject: [PATCH 016/138] Improved iframe handling --- database.sql | 4 +- doc/database/db_post-media.md | 2 + src/Content/Post/Entity/PostMedia.php | 112 ++++++++- src/Content/Post/Factory/PostMedia.php | 8 +- src/Content/Post/Repository/PostMedia.php | 73 ++++-- src/Content/Text/BBCode.php | 27 +- src/Model/Item.php | 15 +- src/Model/Post/Media.php | 6 +- src/Protocol/ActivityPub/Processor.php | 4 + src/Protocol/ActivityPub/Receiver.php | 33 +-- src/Util/ParseUrl.php | 230 +++++++++++++++--- static/dbstructure.config.php | 4 +- tests/src/Content/Text/BBCodeTest.php | 59 ++++- .../templates/content/embed-iframe-resize.tpl | 38 +-- view/templates/content/embed-iframe.tpl | 2 +- view/templates/content/iframe.tpl | 4 +- view/theme/frio/css/style.css | 4 +- view/theme/frio/templates/jot.tpl | 6 - view/theme/vier/style.css | 4 +- 19 files changed, 501 insertions(+), 134 deletions(-) diff --git a/database.sql b/database.sql index 45cb0c7274..ea0fd2cb01 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2025.07-rc (Interrupted Fern) --- DB_UPDATE_VERSION 1582 +-- DB_UPDATE_VERSION 1583 -- ------------------------------------------ @@ -1436,6 +1436,8 @@ CREATE TABLE IF NOT EXISTS `post-media` ( `embed-html` text COMMENT 'HTML embed code for this media', `embed-height` smallint unsigned COMMENT 'Height of the embed', `embed-width` smallint unsigned COMMENT 'Width of the embed', + `page-type` varchar(30) COMMENT 'Type of the page (e.g. article, website)', + `schematypes` varchar(255) COMMENT 'Schema types of the page as JSON string', `language` char(3) COMMENT 'Language information about this media in the ISO 639 format', `published` datetime COMMENT 'Publification date of this media', `modified` datetime COMMENT 'Modification date of this media', diff --git a/doc/database/db_post-media.md b/doc/database/db_post-media.md index 85ae290806..198f393842 100644 --- a/doc/database/db_post-media.md +++ b/doc/database/db_post-media.md @@ -37,6 +37,8 @@ Fields | embed-html | HTML embed code for this media | text | YES | | NULL | | | embed-height | Height of the embed | smallint unsigned | YES | | NULL | | | embed-width | Width of the embed | smallint unsigned | YES | | NULL | | +| page-type | Type of the page (e.g. article, website) | varchar(30) | YES | | NULL | | +| schematypes | Schema types of the page as JSON string | varchar(255) | YES | | NULL | | | language | Language information about this media in the ISO 639 format | char(3) | YES | | NULL | | | published | Publification date of this media | datetime | YES | | NULL | | | modified | Modification date of this media | datetime | YES | | NULL | | diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index 1d4b9c09e2..d87fb3b114 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -42,6 +42,8 @@ use Psr\Http\Message\UriInterface; * @property-read ?string $embedHtml * @property-read ?int $embedWidth * @property-read ?int $embedHeight + * @property-read ?string $pageType + * @property-read ?array $schemaTypes * @property-read ?int $attachId * @property-read ?string $language * @property-read ?string $published @@ -131,6 +133,10 @@ class PostMedia extends BaseEntity protected $embedWidth; /** @var ?int In pixels */ protected $embedHeight; + /** @var ?string */ + protected $pageType; + /** @var ?array */ + protected $schemaTypes; public function __construct( int $uriId, @@ -164,7 +170,9 @@ class PostMedia extends BaseEntity ?string $embedType = null, ?string $embedHtml = null, ?int $embedWidth = null, - ?int $embedHeight = null + ?int $embedHeight = null, + ?string $pageType = null, + ?array $schemaTypes = null ) { $this->uriId = $uriId; $this->url = $url; @@ -198,8 +206,102 @@ class PostMedia extends BaseEntity $this->embedHtml = $embedHtml; $this->embedWidth = $embedWidth; $this->embedHeight = $embedHeight; + $this->pageType = $pageType; + $this->schemaTypes = $schemaTypes; } + /** + * Checks if the media has a player url set + * + * @return boolean + */ + public function hasPlayerUrl(): bool + { + return !is_null($this->playerUrl) && $this->playerUrl !== ''; + } + + /** + * Checks if the media has a player width set + * + * @return boolean + */ + public function hasPlayerWidth(): bool + { + return !is_null($this->playerWidth) && $this->playerWidth > 0; + } + + /** + * Checks if the media has a player height set + * + * @return boolean + */ + public function hasPlayerHeight(): bool + { + return !is_null($this->playerHeight) && $this->playerHeight > 0; + } + + /** + * Checks if the media has an embed html set + * + * @return boolean + */ + public function hasEmbedHtml(): bool + { + return !is_null($this->embedHtml) && $this->embedHtml !== ''; + } + + /** + * Checks if the media has an embed width set + * + * @return boolean + */ + public function hasEmbedWidth(): bool + { + return !is_null($this->embedWidth) && $this->embedWidth > 0; + } + + /** + * Checks if the media has an embed height set + * + * @return boolean + */ + public function hasEmbedHeight(): bool + { + return !is_null($this->embedHeight) && $this->embedHeight > 0; + } + + /** + * Checks if the media is a photo + * + * @return boolean + */ + public function isPhoto(): bool + { + return $this->embedType === 'photo'; + } + + /** + * Checks if the media is a video + * + * @return boolean + */ + public function isVideo(): bool + { + return $this->embedType === 'video' || $this->getPageType() === 'video'; + } + + /** + * Get the page type. In case of a type with main und sub category (separated by `.`), only the main category is returned + * + * @return string|null + */ + public function getPageType(): ?string + { + if (is_null($this->pageType)) { + return null; + } + return explode('.', $this->pageType)[0]; + } /** * Get media link for given media id @@ -313,7 +415,9 @@ class PostMedia extends BaseEntity $this->embedType, $this->embedHtml, $this->embedWidth, - $this->embedHeight + $this->embedHeight, + $this->pageType, + $this->schemaTypes ); } @@ -351,7 +455,9 @@ class PostMedia extends BaseEntity $this->embedType, $this->embedHtml, $this->embedWidth, - $this->embedHeight + $this->embedHeight, + $this->pageType, + $this->schemaTypes ); } diff --git a/src/Content/Post/Factory/PostMedia.php b/src/Content/Post/Factory/PostMedia.php index af45a5c8a3..5bba3140f5 100644 --- a/src/Content/Post/Factory/PostMedia.php +++ b/src/Content/Post/Factory/PostMedia.php @@ -68,7 +68,9 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow $row['embed-type'], $row['embed-html'], $row['embed-width'], - $row['embed-height'] + $row['embed-height'], + $row['page-type'], + $row['schematypes'] ? json_decode($row['schematypes'], true) : null ); } @@ -141,6 +143,8 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow 'embed-html' => $attachment['embed_html'] ?? null, 'embed-width' => $attachment['embed_width'] ?? null, 'embed-height' => $attachment['embed_height'] ?? null, + 'page-type' => $attachment['page_type'] ?? null, + 'schematypes' => null, 'attach-id' => null, 'language' => null, 'published' => null, @@ -190,10 +194,12 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow 'embed-html' => $data['embed']['html'] ?? null, 'embed-width' => $data['embed']['width'] ?? null, 'embed-height' => $data['embed']['height'] ?? null, + 'page-type' => $data['pagetype'] ?? null, 'attach-id' => null, 'language' => $data['language'] ?? null, 'published' => $data['published'] ?? null, 'modified' => $data['modified'] ?? null, + 'schematypes' => isset($data['schematypes']) ? json_encode($data['schematypes']) : null, ]; return $this->createFromTableRow($row); diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index eae63e11b6..5c71d9bad0 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -150,6 +150,8 @@ class PostMedia extends BaseRepository 'embed-html' => $PostMedia->embedHtml, 'embed-height' => $PostMedia->embedHeight, 'embed-width' => $PostMedia->embedWidth, + 'page-type' => $PostMedia->pageType, + 'schematypes' => $PostMedia->schemaTypes ? json_encode($PostMedia->schemaTypes) : null, 'attach-id' => $PostMedia->attachId, 'language' => $PostMedia->language, 'published' => $PostMedia->published, @@ -367,10 +369,10 @@ class PostMedia extends BaseRepository $player = $this->getAudioAttachment($media); } elseif (in_array($media->type, [Post\Media::VIDEO, Post\Media::HLS])) { $player = $this->getVideoAttachment($media, $uid); - } elseif ($allow_embed && !empty($media->playerUrl)) { + } elseif ($allow_embed && $media->hasPlayerUrl() && $media->hasPlayerHeight()) { $player = $this->getPlayerIframe($media); - } elseif ($allow_embed && !empty($media->embedHtml)) { - $player = '' . $this->getEmbedIframe($media) . ''; + } elseif ($allow_embed && $media->hasEmbedHtml() && !$media->isPhoto()) { + $player = $this->getEmbedIframe($media); } else { $player = $this->getLinkAttachment($media); } @@ -408,9 +410,9 @@ class PostMedia extends BaseRepository $width = '100%'; } - if ($this->pConfig->get($uid, 'system', 'embed_media', false) && ($postMedia->playerUrl != '') && ($postMedia->playerHeight > 0)) { + if ($this->pConfig->get($uid, 'system', 'embed_media', false) && $postMedia->hasPlayerUrl() && $postMedia->hasPlayerHeight()) { $media = $this->getPlayerIframe($postMedia); - } elseif ($this->pConfig->get($uid, 'system', 'embed_media', false) && ($postMedia->embedHtml != '')) { + } elseif ($this->pConfig->get($uid, 'system', 'embed_media', false) && $postMedia->hasEmbedHtml() && !$postMedia->isPhoto()) { $media = $this->getEmbedIframe($postMedia); } else { /// @todo Move the template to /content as well @@ -436,22 +438,33 @@ class PostMedia extends BaseRepository return ''; } - $div_style = ''; $iframe_style = ''; - $height = min($this->config->get('system', 'max_height'), $postMedia->playerHeight); + $height = '100%'; + $width = '100%'; - if ($postMedia->playerWidth != 0 && $postMedia->playerHeight != 0 && $postMedia->playerWidth > $this->config->get('system', 'max_width') && $postMedia->playerWidth > $postMedia->playerHeight) { - $factor = round($postMedia->playerHeight / $postMedia->playerWidth, 2) * 100; - $height = '100%'; - $iframe_style .= 'position:absolute;left:0px;top:0px;'; - $div_style .= 'position:relative;padding-bottom:' . $factor . '%;'; + if ($postMedia->isVideo()) { + if ($postMedia->hasPlayerWidth() && $postMedia->hasPlayerHeight()) { + $iframe_style .= 'aspect-ratio:' . $postMedia->playerWidth . '/' . $postMedia->playerHeight . ';'; + if ($postMedia->playerWidth < $postMedia->playerHeight) { + $height = $postMedia->playerHeight; + $width = ''; + } else { + $height = ''; + } + } + } else { + if ($postMedia->hasPlayerHeight()) { + $height = $postMedia->playerHeight . 'px'; + } + if ($postMedia->hasPlayerWidth()) { + $width = $postMedia->playerWidth . 'px'; + } } return Renderer::replaceMacros(Renderer::getMarkupTemplate('content/iframe.tpl'), [ 'src' => $postMedia->playerUrl, 'height' => $height, - 'width' => $postMedia->embedWidth && $postMedia->embedWidth <= $this->config->get('system', 'max_width') ? $postMedia->embedWidth : '100%', - 'div_style' => $div_style, + 'width' => $width, 'iframe_style' => $iframe_style, ]); } @@ -462,11 +475,35 @@ class PostMedia extends BaseRepository return ''; } + $iframe_style = ''; + $height = '100%'; + $width = '100%'; + + if ($postMedia->isVideo()) { + if ($postMedia->hasEmbedWidth() && $postMedia->hasEmbedHeight()) { + $iframe_style .= 'aspect-ratio:' . $postMedia->embedWidth . '/' . $postMedia->embedHeight . ';'; + if ($postMedia->embedWidth < $postMedia->embedHeight) { + $height = $postMedia->embedHeight; + $width = ''; + } else { + $height = ''; + } + } + } else { + if ($postMedia->hasEmbedHeight()) { + $height = $postMedia->embedHeight . 'px'; + } + if ($postMedia->hasEmbedWidth()) { + $width = $postMedia->embedWidth . 'px'; + } + } + return Renderer::replaceMacros(Renderer::getMarkupTemplate($postMedia->embedHeight ? 'content/embed-iframe.tpl' : 'content/embed-iframe-resize.tpl'), [ - 'id' => 'iframe-' . hash('md5', $postMedia->embedHtml), - 'src' => $postMedia->embedHtml, - 'height' => $postMedia->embedHeight + 20, - 'width' => $postMedia->embedWidth && $postMedia->embedWidth <= $this->config->get('system', 'max_width') ? $postMedia->embedWidth : '100%', + 'id' => 'iframe-' . hash('md5', $postMedia->embedHtml), + 'src' => $postMedia->embedHtml, + 'height' => $height, + 'width' => $width, + 'iframe_style' => $iframe_style, ]); } diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index ef4cf32e56..ec47d8aad4 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -443,19 +443,26 @@ class BBCode $return = sprintf('
          ', $data['type']); } - if ($embed && (($data['player_url'] != '' && $data['player_height'] != 0) || $data['embed_html'] != '')) { + if ($embed) { $media = DI::postMediaFactory()->createFromAttachment($data, $uriid); - if ($data['player_url'] != '' && $data['player_height'] != 0) { - $return .= DI::postMediaRepository()->getPlayerIframe($media); + if ($media->hasPlayerUrl() && $media->hasPlayerHeight()) { + $embed_media = DI::postMediaRepository()->getPlayerIframe($media); + } elseif ($media->hasEmbedHtml() && !$media->isPhoto()) { + $embed_media = DI::postMediaRepository()->getEmbedIframe($media); } else { - $return .= DI::postMediaRepository()->getEmbedIframe($media); + $embed_media = null; + } + + if ($embed_media) { + $return .= $embed_media; + + $preview_mode = self::PREVIEW_NO_IMAGE; + unset($data['title']); + unset($data['url']); + unset($data['description']); + unset($data['provider_url']); + unset($data['provider_name']); } - $preview_mode = self::PREVIEW_NO_IMAGE; - unset($data['title']); - unset($data['url']); - unset($data['description']); - unset($data['provider_url']); - unset($data['provider_name']); } if ($preview_mode == self::PREVIEW_NO_IMAGE) { diff --git a/src/Model/Item.php b/src/Model/Item.php index 72334e4183..9e6b27217c 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3034,7 +3034,7 @@ class Item if (!empty($sharedSplitAttachments)) { $s = self::addGallery($s, $sharedSplitAttachments['visual']); $s = self::addVisualAttachments($sharedSplitAttachments['visual'], $shared_item, $s, true, $uid); - $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid); + $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid, $shared_item); $s = self::addNonVisualAttachments($sharedSplitAttachments['additional'], $item, $s); $body = BBCode::removeSharedData($body); } @@ -3047,7 +3047,7 @@ class Item $s = self::addGallery($s, $itemSplitAttachments['visual']); $s = self::addVisualAttachments($itemSplitAttachments['visual'], $item, $s, false, $uid); - $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid); + $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid, $item); $s = self::addNonVisualAttachments($itemSplitAttachments['additional'], $item, $s); $s = self::addQuestions($item, $s); @@ -3359,16 +3359,18 @@ class Item * @param bool $shared * @param array $ignore_links A list of URLs to ignore * @param int $uid + * @param array $item * @return string modified content * @throws InternalServerErrorException * @throws ServiceUnavailableException */ - private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid): string + private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid, array $item): string { DI::profiler()->startRecording('rendering'); // Don't show a preview when there is a visual attachment (audio or video) - $types = $attachments['visual']->column('type'); - $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $types = $attachments['visual']->column('type'); + $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $has_media = in_array($item['post-type'] ?? null, [Item::PT_AUDIO, Item::PT_VIDEO]); /** @var ?PostMedia $attachment */ $attachment = null; @@ -3409,6 +3411,7 @@ class Item 'embed_html' => $attachment->embedHtml, 'embed_width' => $attachment->embedWidth, 'embed_height' => $attachment->embedHeight, + 'page_type' => $attachment->pageType, ]; if ($preview && $attachment->preview) { @@ -3460,7 +3463,7 @@ class Item // @todo Use a template $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); - if ($preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { + if (!$has_media && $preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, $data, $uriid, $preview_mode, DI::pConfig()->get($uid, 'system', 'embed_remote_media', false)); } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { $rendered = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 764175d629..22d62368f5 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -479,18 +479,20 @@ class Media $media['embed-html'] = $data['embed']['html'] ?? null; $media['embed-height'] = $data['embed']['height'] ?? null; $media['embed-width'] = $data['embed']['width'] ?? null; + $media['page-type'] = $data['pagetype'] ?? null; $media['language'] = $data['language'] ?? null; $media['published'] = $data['published'] ?? null; $media['modified'] = $data['modified'] ?? null; + $media['schematypes'] = isset($data['schematypes']) ? json_encode($data['schematypes']) : null; if (DI::config()->get('system', 'add_page_media')) { - if (!empty($data['audio'])) { + if (isset($data['audio']) && sizeof($data['audio']) == 1) { foreach ($data['audio'] as $entry) { self::insertMedia($entry, $media['uri-id']); } } - if (!empty($data['video'])) { + if (isset($data['video']) && sizeof($data['video']) == 1) { foreach ($data['video'] as $entry) { self::insertMedia($entry, $media['uri-id']); } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index e714a1d9c1..d854191d73 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -158,6 +158,10 @@ class Processor $data['player-url'] = $attachment['player-url'] ?? null; $data['player-height'] = $attachment['player-height'] ?? null; $data['player-width'] = $attachment['player-width'] ?? null; + $data['embed-type'] = $attachment['embed-type'] ?? null; + $data['embed-html'] = $attachment['embed-html'] ?? null; + $data['embed-width'] = $attachment['embed-width'] ?? null; + $data['embed-height'] = $attachment['embed-height'] ?? null; Post\Media::insert($data); } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 399d74cd63..e9092ab768 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -1867,9 +1867,10 @@ class Receiver * @param array $urls The object URL list * @param string|null $icon The icon URL to use for the attachments * @param array $player Embedded player data (url, width, height) + * @param array $embed oEmbed data (html, width, height) * @return array an array of attachments */ - private static function processAttachmentUrls(array $urls, ?string $icon, array $player): array + private static function processAttachmentUrls(array $urls, ?string $icon, array $player, array $embed): array { $attachments = []; foreach ($urls as $key => $url) { @@ -1918,30 +1919,27 @@ class Receiver } elseif ($mediatype == 'application/x-mpegURL') { // PeerTube uses HLS streams for video. We prefer HLS streams over the video file itself. // But we still store the video file as an attachment to be used by the API which currently does not support HLS streams. - $attachments = array_merge($attachments, self::processAttachmentUrls($url['as:tag'], $icon, [])); + $attachments = array_merge($attachments, self::processAttachmentUrls($url['as:tag'], $icon, [], [])); $attachment = ['type' => $filetype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '', 'image' => $icon]; - if (!empty($player)) { + if (is_array($player)) { $attachment['player-url'] = $player['embed'] ?? null; $attachment['player-height'] = $player['height'] ?? null; $attachment['player-width'] = $player['width'] ?? null; - if (is_null($attachment['player-height']) && is_null($attachment['player-width'])) { - foreach ($attachments as $media) { - if (isset($media['height']) && isset($media['width'])) { - if ($media['height'] > $attachment['player-height'] || $media['width'] > $attachment['player-width']) { - $attachment['player-height'] = $media['height']; - $attachment['player-width'] = $media['width']; - } - } - } - } - if (!$height && !$width) { $attachment['height'] = $attachment['player-height']; $attachment['width'] = $attachment['player-width']; } } + + if (is_array($embed)) { + $attachment['embed-type'] = $embed['type'] ?? null; + $attachment['embed-html'] = $embed['html'] ?? null; + $attachment['embed-height'] = $embed['height'] ?? null; + $attachment['embed-width'] = $embed['width'] ?? null; + } + DI::logger()->info('Adding video attachment', ['attachment' => $attachment]); $attachments[] = $attachment; } @@ -2130,8 +2128,13 @@ class Receiver } else { $player = []; } + if (isset($siteinfo['embed'])) { + $embed = $siteinfo['embed']; + } else { + $embed = []; + } - $object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? [], self::processIcon($object), $player)); + $object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? [], self::processIcon($object), $player, $embed)); } $object_data['can-comment'] = JsonLD::fetchElement($object, 'pt:commentsEnabled', '@value'); diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index c748c050e6..761b35b2f9 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -22,6 +22,7 @@ use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Network\HTTPClient\Client\HttpClientRequest; use Embera\Embera; use Friendica\Content\Text\BBCode; +use Friendica\Core\Cache\Enum\Duration; use Friendica\Model\Post; /** @@ -459,6 +460,9 @@ class ParseUrl case 'og:description': $siteinfo['text'] = trim($meta_tag['content']); break; + case 'og:updated_time': + $siteinfo['modified'] = DateTimeFormat::utc(trim($meta_tag['content'])); + break; case 'og:site_name': $siteinfo['publisher_name'] = trim($meta_tag['content']); break; @@ -494,16 +498,24 @@ class ParseUrl } } + $siteinfo['schematypes'] = []; + $list = $xpath->query("//script[@type='application/ld+json']"); foreach ($list as $node) { if (!empty($node->nodeValue)) { $jsonld = json_decode($node->nodeValue, true); if (is_array($jsonld)) { - $siteinfo = self::parseParts($siteinfo, $jsonld); + $siteinfo = self::parseParts($siteinfo, $jsonld, true); } } } + $siteinfo['schematypes'] = array_values(array_unique($siteinfo['schematypes'])); + + if (sizeof($siteinfo['schematypes']) === 0) { + unset($siteinfo['schematypes']); + } + $siteinfo = self::getOembedInfo($xpath, $siteinfo); if (!empty($siteinfo['player']['stream'])) { @@ -595,7 +607,7 @@ class ParseUrl foreach (['audio', 'video'] as $element) { if (!empty($siteinfo[$element])) { - array_walk($siteinfo[$element], function (&$media) use ($page_url, &$siteinfo) { + array_walk($siteinfo[$element], function (&$media) use ($page_url) { $url = ''; $embed = ''; $content = ''; @@ -630,9 +642,6 @@ class ParseUrl } if (!empty($embed)) { $media['embed'] = $embed; - if (empty($siteinfo['player']['embed'])) { - $siteinfo['player']['embed'] = $embed; - } } if (!empty($content)) { $media['src'] = $content; @@ -748,16 +757,16 @@ class ParseUrl * * @return array siteinfo */ - private static function parseParts(array $siteinfo, array $jsonld): array + private static function parseParts(array $siteinfo, array $jsonld, bool $root): array { if (!empty($jsonld['@graph']) && is_array($jsonld['@graph'])) { foreach ($jsonld['@graph'] as $part) { if (!empty($part) && is_array($part)) { - $siteinfo = self::parseParts($siteinfo, $part); + $siteinfo = self::parseParts($siteinfo, $part, false); } } } elseif (!empty($jsonld['@type'])) { - $siteinfo = self::parseJsonLd($siteinfo, $jsonld); + $siteinfo = self::parseJsonLd($siteinfo, $jsonld, $root); } elseif (!empty($jsonld)) { $keys = array_keys($jsonld); $numeric_keys = true; @@ -769,7 +778,7 @@ class ParseUrl if ($numeric_keys) { foreach ($jsonld as $part) { if (!empty($part) && is_array($part)) { - $siteinfo = self::parseParts($siteinfo, $part); + $siteinfo = self::parseParts($siteinfo, $part, false); } } } @@ -794,7 +803,7 @@ class ParseUrl * * @return array siteinfo */ - private static function parseJsonLd(array $siteinfo, array $jsonld): array + private static function parseJsonLd(array $siteinfo, array $jsonld, bool $root): array { $type = JsonLD::fetchElement($jsonld, '@type'); if (empty($type)) { @@ -802,6 +811,10 @@ class ParseUrl return $siteinfo; } + if ($root) { + $siteinfo['schematypes'][] = $type; + } + // Silently ignore some types that aren't processed if (in_array($type, ['SiteNavigationElement', 'JobPosting', 'CreativeWork', 'MusicAlbum', 'WPHeader', 'WPSideBar', 'WPFooter', 'LegalService', 'MusicRecording', @@ -1321,6 +1334,18 @@ class ParseUrl DI::logger()->debug('Using Twitter oEmbed', ['url' => $url, 'oembed' => $oembed]); } + if (in_array(parse_url(Strings::normaliseLink($url), PHP_URL_HOST), ['tidal.com'])) { + $oembed = 'https://oembed.tidal.com?url=' . urlencode($url); + DI::logger()->debug('Using Tidal oEmbed', ['url' => $url, 'oembed' => $oembed]); + // @todo Check how to support the parameters listed here: https://developer.tidal.com/documentation/embeds/embeds-code-generator + } + + if (in_array(parse_url(Strings::normaliseLink($url), PHP_URL_HOST), ['link.deezer.com', 'deezer.com', 'www.deezer.com'])) { + $oembed = 'https://api.deezer.com/oembed?url=' . urlencode($url) . '&tracklist=true'; + DI::logger()->debug('Using Deezer oEmbed', ['url' => $url, 'oembed' => $oembed]); + // @see https://developers.deezer.com/api/oembed + } + if (!$oembed) { foreach ($xpath->query("//link[@type='application/json+oembed']") as $link) { /** @var DOMElement $link */ @@ -1329,6 +1354,10 @@ class ParseUrl } } + if (!$oembed) { + $oembed = self::fetchFromProviderList($url); + } + if ($oembed) { $oembed .= '&maxwidth=' . DI::config()->get('system', 'max_width') . '&maxheight=' . DI::config()->get('system', 'max_height') . '&format=json'; $result = DI::httpClient()->get($oembed, HttpClientAccept::DEFAULT, [HttpClientOptions::REQUEST => HttpClientRequest::SITEINFO]); @@ -1346,9 +1375,71 @@ class ParseUrl $data = current($urldata); DI::logger()->debug('Found oEmbed JSON from Embera', ['url' => $url]); } + + if (!isset($data['type']) || !isset($data['provider_url'])) { + return []; + } + + // Some provider return "rich", although they should return "photo" + if ($data['type'] === 'rich' && in_array($data['provider_url'], ['https://www.pixiv.net/', 'https://www.pinterest.com'])) { + $data['type'] = 'photo'; + } + return $data; } + /** + * Fetch the oEmbed provider from the oembed.com provider list + * + * @param string $url The url to fetch the oEmbed provider for + * + * @return string|null The oEmbed url or null if no provider was found + */ + private static function fetchFromProviderList(string $url): ?string + { + $cachekey = 'ParseUrl:fetchFromProviderList'; + + $providers = DI::cache()->get($cachekey); + if (!$providers) { + $providers_content = DI::httpClient()->fetch('https://oembed.com/providers.json', HttpClientAccept::JSON, 0, '', HttpClientRequest::SITEINFO); + if (!$providers_content) { + DI::logger()->warning('Could not fetch oEmbed provider list'); + return null; + } + $providers = json_decode($providers_content, true); + if (!is_array($providers)) { + DI::logger()->warning('Could not decode oEmbed provider list'); + return null; + } + DI::cache()->set($cachekey, $providers, Duration::WEEK); + } + $schemes = []; + foreach ($providers as $provider) { + if (!isset($provider['endpoints']) || !is_array($provider['endpoints'])) { + continue; + } + foreach ($provider['endpoints'] as $endpoint) { + if (!isset($endpoint['schemes']) || !is_array($endpoint['schemes'])) { + $schemes[rtrim($provider['provider_url'], '/') . '/*'] = str_replace('{format}', 'json', $endpoint['url']); + continue; + } + foreach ($endpoint['schemes'] as $scheme) { + $schemes[$scheme] = str_replace('{format}', 'json', $endpoint['url']); + } + } + } + + foreach ($schemes as $scheme => $provider_url) { + $regex = str_replace(['.', '?', '*'], ['\.', '\?', '.*'], $scheme); + if (preg_match('~' . $regex . '~i', $url)) { + $oembed = $provider_url . (strpos($provider_url, '?') === false ? '?' : '&') . 'url=' . urlencode($url); + DI::logger()->debug('Found oEmbed provider from oembed.com list', ['url' => $url, 'oembed' => $oembed]); + return $oembed; + } + } + return null; + } + private static function getSiteinfoFromoEmbed(array $siteinfo, array $data): array { // Youtube provides only basic information to some IP ranges. @@ -1358,31 +1449,34 @@ class ParseUrl $unknown_fields = $data; foreach (['account_type', 'asset_type', 'author_unique_id', 'availability', 'brand', - 'cache_age', 'category', 'currency_code', 'duration', 'embera_using_fake_response', - 'embera_provider_name', 'embed_product_id', 'embed_type', 'flickr_type', - 'height', 'html', 'images','iframe_url', 'is_plus', 'price', 'products', - 'product_expiration', 'product_id', 'quantity', 'referrer', 'safety', 'success', 'type', - 'thumbnail_credit', 'thumbnail_credit_url', 'thumbnail_credit_note', + 'cache_age', 'category', 'collection', 'currency_code', 'duration', 'embera_using_fake_response', + 'embera_provider_name', 'embed_product_id', 'embed_type', 'embed', 'entity', 'flickr_type', + 'height', 'html', 'id', 'images','iframe_url', 'is_plus', 'photographer', 'price', 'products', + 'product_expiration', 'product_id', 'quantity', 'ratio', 'referrer', 'safety', 'success', + 'terms_of_use_url', 'type', 'thumbnail_credit', 'thumbnail_credit_url', 'thumbnail_credit_note', 'thumbnail_height', 'thumbnail_url_with_play_button', 'thumbnail_width', - 'uri', 'url', 'version', 'video_id', 'web_page', 'web_page_short_url', 'width'] as $value) { + 'uri', 'url', 'version', 'video_id', 'web_page', 'web_page_short_url', 'width', 'work_type'] as $value) { unset($unknown_fields[$value]); } $fields = [ - 'title' => 'title', - 'description' => 'text', - 'summary' => 'text', - 'author_name' => 'author_name', - 'author_url' => 'author_url', - 'author' => 'author_name', - 'provider_name' => 'publisher_name', - 'provider_url' => 'publisher_url', - 'thumbnail_url' => 'image', - 'upload_date' => 'published', - 'publication_date' => 'published', - 'license' => 'license_name', - 'license_url' => 'license_url', - 'license_id' => 'license_id', + 'title' => 'title', + 'caption' => 'text', + 'description' => 'text', + 'summary' => 'text', + 'video_description' => 'text', + 'author_name' => 'author_name', + 'author_url' => 'author_url', + 'author' => 'author_name', + 'provider_name' => 'publisher_name', + 'provider_url' => 'publisher_url', + 'image' => 'image', + 'thumbnail_url' => 'image', + 'upload_date' => 'published', + 'publication_date' => 'published', + 'license' => 'license_name', + 'license_url' => 'license_url', + 'license_id' => 'license_id', ]; foreach ($fields as $key => $value) { @@ -1407,12 +1501,16 @@ class ParseUrl private static function getOembedInfo(DOMXPath $xpath, array $siteinfo): array { $data = self::getOembedData($xpath, $siteinfo['url']); - if (empty($data) || !is_array($data)) { + if (!$data) { return $siteinfo; } $siteinfo = self::getSiteinfoFromoEmbed($siteinfo, $data); + if (!self::isWantedEmbed($siteinfo, $data)) { + return $siteinfo; + } + if ($data['type'] == 'video' & empty($siteinfo['player']) && ($data['provider_url'] ?? '') == 'https://www.tiktok.com' && isset($data['embed_product_id']) && isset($data['thumbnail_width']) && isset($data['thumbnail_height'])) { $siteinfo['embed']['type'] = $data['type']; $siteinfo['embed']['html'] = trim($data['html']); @@ -1424,10 +1522,18 @@ class ParseUrl return $siteinfo; } + if ($data['provider_url'] == 'https://www.pinterest.com' && isset($siteinfo['video'])) { + $data['type'] = 'video'; + } + if (!isset($data['html'])) { return $siteinfo; } + if (strpos($data['html'], '<') === 0) { + $data['html'] = html_entity_decode($data['html']); + } + unset($siteinfo['player']); if ($data['type'] == 'rich' && !isset($siteinfo['text'])) { @@ -1455,7 +1561,7 @@ class ParseUrl $curlResult = DI::httpClient()->head($link); $redirect = $curlResult->getRedirectUrl(); if (preg_match('#/(video|broadcasts)/#', $redirect)) { - $siteinfo['embed']['type'] = $data['type']; + $siteinfo['embed']['type'] = 'video'; $siteinfo['embed']['html'] = trim(str_replace('
          - - diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 789ca6b4bc..d0fb3dfaaa 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -3299,8 +3299,8 @@ fbrowser.photo .photo-album-image-wrapper { margin-left: 10px; } text-align: center; } -iframe, +iframe.embed, video { max-width: 100%; - max-height: 90vh; + max-height: calc(100vh - 150px); } From d286f6ba9cd1d710130a9a1405b19211b810deb2 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 21 Oct 2025 05:07:33 +0000 Subject: [PATCH 017/138] Issue 15191: Fix poll frequency calculation --- src/Protocol/Feed.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 48780e6181..9f1e0fac86 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -279,8 +279,7 @@ class Feed return []; } - $items = []; - $creation_dates = []; + $items = []; // Limit the number of items that are about to be fetched $total_items = ($entries->length - 1); @@ -289,7 +288,10 @@ class Feed $total_items = $max_items; } - $postings = self::importOlderEntries($entries, $total_items, $header, $author, $contact, $importer, $xpath, $atomns, $basepath, $dryRun); + $processed = self::processEntries($entries, $total_items, $header, $author, $contact, $importer, $xpath, $atomns, $basepath, $dryRun); + + $postings = $processed['postings']; + $creation_dates = $processed['creation_dates']; if (!empty($postings)) { $min_posting = DI::config()->get('system', 'minimum_posting_interval', 0); @@ -358,9 +360,10 @@ class Feed return $title; } - private static function importOlderEntries(DOMNodeList $entries, int $total_items, array $header, array $author, array $contact, array $importer, DOMXPath $xpath, string $atomns, string $basepath, bool $dryRun): array + private static function processEntries(DOMNodeList $entries, int $total_items, array $header, array $author, array $contact, array $importer, DOMXPath $xpath, string $atomns, string $basepath, bool $dryRun): array { - $postings = []; + $postings = []; + $creation_dates = []; // Importing older entries first for ($i = $total_items; $i >= 0; --$i) { @@ -762,7 +765,7 @@ class Feed } } - return $postings; + return ['postings' => $postings, 'creation_dates' => $creation_dates]; } /** From 95613cf4e858733266421cc16b178a5cdfe9f7a7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 Oct 2025 06:18:55 +0000 Subject: [PATCH 018/138] Don't store MP4 video when processing HLS video --- src/Protocol/ActivityPub/Receiver.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index e9092ab768..86e10453e3 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -1917,10 +1917,6 @@ class Receiver $attachments[$mediatype] = ['type' => $mediatype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '']; } elseif ($mediatype == 'application/x-mpegURL') { - // PeerTube uses HLS streams for video. We prefer HLS streams over the video file itself. - // But we still store the video file as an attachment to be used by the API which currently does not support HLS streams. - $attachments = array_merge($attachments, self::processAttachmentUrls($url['as:tag'], $icon, [], [])); - $attachment = ['type' => $filetype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '', 'image' => $icon]; if (is_array($player)) { $attachment['player-url'] = $player['embed'] ?? null; From 319cdbe44386b9d1548eb7c2a810fdc2b3fb3783 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 Oct 2025 07:25:25 +0000 Subject: [PATCH 019/138] Attach single media to post --- src/Model/Post/Media.php | 2 +- src/Protocol/Feed.php | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 22d62368f5..b38b6191c0 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -485,7 +485,7 @@ class Media $media['modified'] = $data['modified'] ?? null; $media['schematypes'] = isset($data['schematypes']) ? json_encode($data['schematypes']) : null; - if (DI::config()->get('system', 'add_page_media')) { + if (!isset($media['player-url']) && !isset($media['embed-html']) && DI::config()->get('system', 'add_page_media')) { if (isset($data['audio']) && sizeof($data['audio']) == 1) { foreach ($data['audio'] as $entry) { self::insertMedia($entry, $media['uri-id']); diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 9f1e0fac86..7fc87085a3 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -688,29 +688,6 @@ class Feed $taglist = $fetch_further_information == LocalRelationship::FFI_BOTH ? PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? '') : []; $item['object-type'] = Activity\ObjectType::BOOKMARK; $attachments = []; - - foreach (['audio', 'video'] as $elementname) { - if (!empty($data[$elementname])) { - foreach ($data[$elementname] as $element) { - if (!empty($element['src'])) { - $src = $element['src']; - } elseif (!empty($element['content'])) { - $src = $element['content']; - } else { - continue; - } - - $attachments[] = [ - 'type' => ($elementname == 'audio') ? Post\Media::AUDIO : Post\Media::VIDEO, - 'url' => $src, - 'preview' => $element['image'] ?? null, - 'mimetype' => $element['contenttype'] ?? null, - 'name' => $element['name'] ?? null, - 'description' => $element['description'] ?? null, - ]; - } - } - } } } else { if ($fetch_further_information == LocalRelationship::FFI_KEYWORD) { From d21e319bef147f241501436895d845d0b30a28fb Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 22 Oct 2025 15:28:52 +0000 Subject: [PATCH 020/138] Automatic preview size size detection --- src/Content/Post/Entity/PostMedia.php | 18 ++ src/Content/Text/BBCode.php | 5 +- src/Model/Item.php | 13 +- src/Module/Settings/Display.php | 3 +- view/lang/C/messages.po | 274 +++++++++++++------------- 5 files changed, 171 insertions(+), 142 deletions(-) diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index d87fb3b114..a9e1f2b7c6 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -290,6 +290,24 @@ class PostMedia extends BaseEntity return $this->embedType === 'video' || $this->getPageType() === 'video'; } + /** + * Checks if the media is an article + * + * @return boolean + */ + public function isArticle(): bool + { + if (is_array($this->schemaTypes)) { + foreach (['Article', 'BackgroundNewsArticle', 'NewsArticle'] as $type) { + if (in_array($type, $this->schemaTypes)) { + return true; + } + } + } + + return in_array($this->getPageType(), ['article']); + } + /** * Get the page type. In case of a type with main und sub category (separated by `.`), only the main category is returned * diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index ec47d8aad4..874ca6de1f 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -58,6 +58,7 @@ class BBCode const PREVIEW_NO_IMAGE = 1; const PREVIEW_LARGE = 2; const PREVIEW_SMALL = 3; + const PREVIEW_AUTO = 4; /** * Fetches attachment data that were generated with the "attachment" element @@ -412,7 +413,7 @@ class BBCode * @return string * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, array $data = [], int $uriid = 0, int $preview_mode = self::PREVIEW_LARGE, bool $embed = false): string + public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, array $data = [], int $uriid = 0, int $preview_mode = self::PREVIEW_AUTO, bool $embed = false): string { DI::profiler()->startRecording('rendering'); $data = $data ?: self::getAttachmentData($text); @@ -471,7 +472,7 @@ class BBCode } if (!empty($data['title']) && !empty($data['url'])) { - $preview_class = $preview_mode == self::PREVIEW_LARGE ? 'attachment-image' : 'attachment-preview'; + $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; if (!empty($data['image']) && empty($data['text']) && ($data['type'] == 'photo')) { $return .= sprintf('', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); } else { diff --git a/src/Model/Item.php b/src/Model/Item.php index 9e6b27217c..2fea1d117b 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3368,9 +3368,10 @@ class Item { DI::profiler()->startRecording('rendering'); // Don't show a preview when there is a visual attachment (audio or video) - $types = $attachments['visual']->column('type'); - $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); - $has_media = in_array($item['post-type'] ?? null, [Item::PT_AUDIO, Item::PT_VIDEO]); + $types = $attachments['visual']->column('type'); + $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $has_media = in_array($item['post-type'] ?? null, [Item::PT_AUDIO, Item::PT_VIDEO]); + $is_article = false; /** @var ?PostMedia $attachment */ $attachment = null; @@ -3413,6 +3414,7 @@ class Item 'embed_height' => $attachment->embedHeight, 'page_type' => $attachment->pageType, ]; + $is_article = $attachment->isArticle(); if ($preview && $attachment->preview) { if ($attachment->previewWidth >= 500) { @@ -3462,7 +3464,10 @@ class Item } // @todo Use a template - $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); + $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_AUTO); + if ($preview_mode == BBCode::PREVIEW_AUTO) { + $preview_mode = $is_article ? BBCode::PREVIEW_SMALL : BBCode::PREVIEW_LARGE; + } if (!$has_media && $preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, $data, $uriid, $preview_mode, DI::pConfig()->get($uid, 'system', 'embed_remote_media', false)); } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 12da8f79eb..895855ddbf 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -259,12 +259,13 @@ class Display extends BaseSettings ContactSelector::SVG_WHITE => $this->t('White'), ]; - $preview_mode = $this->pConfig->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); + $preview_mode = $this->pConfig->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_AUTO); $preview_modes = [ BBCode::PREVIEW_NONE => $this->t('No preview'), BBCode::PREVIEW_NO_IMAGE => $this->t('No image'), BBCode::PREVIEW_SMALL => $this->t('Small Image'), BBCode::PREVIEW_LARGE => $this->t('Large Image'), + BBCode::PREVIEW_AUTO => $this->t('Automatic image size'), ]; $bookmarked_timelines = $this->pConfig->get($uid, 'system', 'network_timelines', $this->getAvailableTimelines($uid, true)->column('code')); diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 755fbbcbca..9b60887480 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2025.07-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-10 20:47+0200\n" +"POT-Creation-Date: 2025-10-22 15:27+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -799,7 +799,7 @@ msgstr "" msgid "Following" msgstr "" -#: src/BaseModule.php:450 src/Content/Widget.php:259 src/Model/User.php:1383 +#: src/BaseModule.php:450 src/Content/Widget.php:259 src/Model/User.php:1386 #: src/Module/Contact.php:405 msgid "Friends" msgstr "" @@ -1374,7 +1374,7 @@ msgstr "" msgid "Public post" msgstr "" -#: src/Content/Conversation.php:417 src/Content/Item.php:439 +#: src/Content/Conversation.php:417 src/Content/Item.php:437 #: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1304 #: src/Model/Profile.php:460 src/Module/Admin/Logs/View.php:80 #: src/Module/Post/Edit.php:177 @@ -1715,7 +1715,7 @@ msgstr "" #: src/Content/Feature.php:127 src/Content/GroupManager.php:128 #: src/Content/Nav.php:276 src/Content/Text/HTML.php:877 -#: src/Content/Widget.php:558 src/Model/User.php:1397 +#: src/Content/Widget.php:558 src/Model/User.php:1400 msgid "Groups" msgstr "" @@ -1750,7 +1750,7 @@ msgstr "" #: src/Content/Feature.php:131 src/Content/Widget.php:613 #: src/Module/Admin/Site.php:459 src/Module/BaseSettings.php:113 -#: src/Module/Settings/Channels.php:216 src/Module/Settings/Display.php:319 +#: src/Module/Settings/Channels.php:216 src/Module/Settings/Display.php:320 msgid "Channels" msgstr "" @@ -1857,35 +1857,35 @@ msgstr "" msgid "%1$s tagged %2$s's %3$s with %4$s" msgstr "" -#: src/Content/Item.php:433 view/theme/frio/theme.php:249 +#: src/Content/Item.php:431 view/theme/frio/theme.php:249 msgid "Follow Thread" msgstr "" -#: src/Content/Item.php:434 src/Model/Contact.php:1299 +#: src/Content/Item.php:432 src/Model/Contact.php:1299 msgid "View Status" msgstr "" -#: src/Content/Item.php:435 src/Content/Item.php:458 src/Model/Contact.php:1234 +#: src/Content/Item.php:433 src/Content/Item.php:456 src/Model/Contact.php:1234 #: src/Model/Contact.php:1290 src/Model/Contact.php:1300 #: src/Module/Directory.php:143 src/Module/Settings/Profile/Index.php:279 msgid "View Profile" msgstr "" -#: src/Content/Item.php:436 src/Model/Contact.php:1301 +#: src/Content/Item.php:434 src/Model/Contact.php:1301 msgid "View Photos" msgstr "" -#: src/Content/Item.php:437 src/Model/Contact.php:1268 +#: src/Content/Item.php:435 src/Model/Contact.php:1268 #: src/Model/Profile.php:443 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:438 src/Model/Contact.php:1292 +#: src/Content/Item.php:436 src/Model/Contact.php:1292 #: src/Model/Contact.php:1303 msgid "View Contact" msgstr "" -#: src/Content/Item.php:440 src/Module/Contact.php:453 +#: src/Content/Item.php:438 src/Module/Contact.php:453 #: src/Module/Contact/Profile.php:564 #: src/Module/Moderation/Blocklist/Contact.php:104 #: src/Module/Moderation/Users/Active.php:93 @@ -1893,7 +1893,7 @@ msgstr "" msgid "Block" msgstr "" -#: src/Content/Item.php:441 src/Module/Contact.php:454 +#: src/Content/Item.php:439 src/Module/Contact.php:454 #: src/Module/Contact/Profile.php:572 #: src/Module/Notifications/Introductions.php:126 #: src/Module/Notifications/Introductions.php:200 @@ -1901,49 +1901,49 @@ msgstr "" msgid "Ignore" msgstr "" -#: src/Content/Item.php:442 src/Module/Contact.php:455 +#: src/Content/Item.php:440 src/Module/Contact.php:455 #: src/Module/Contact/Profile.php:580 msgid "Collapse" msgstr "" -#: src/Content/Item.php:443 src/Object/Post.php:287 +#: src/Content/Item.php:441 src/Object/Post.php:287 #, php-format msgid "Ignore %s server" msgstr "" -#: src/Content/Item.php:447 src/Object/Post.php:508 +#: src/Content/Item.php:445 src/Object/Post.php:508 msgid "Detected languages" msgstr "" -#: src/Content/Item.php:450 src/Object/Post.php:591 +#: src/Content/Item.php:448 src/Object/Post.php:591 msgid "Raw content" msgstr "" -#: src/Content/Item.php:455 src/Content/Widget.php:65 +#: src/Content/Item.php:453 src/Content/Widget.php:65 #: src/Model/Contact.php:1293 src/Model/Contact.php:1305 #: src/Module/Contact/Follow.php:152 view/theme/vier/theme.php:182 msgid "Connect/Follow" msgstr "" -#: src/Content/Item.php:886 +#: src/Content/Item.php:884 msgid "Unable to fetch user." msgstr "" -#: src/Content/Item.php:1348 src/Core/L10n.php:453 +#: src/Content/Item.php:1346 src/Core/L10n.php:453 msgid "Undetermined" msgstr "" -#: src/Content/Item.php:1355 +#: src/Content/Item.php:1353 #, php-format msgid "%s (%s - %s): %s" msgstr "" -#: src/Content/Item.php:1357 +#: src/Content/Item.php:1355 #, php-format msgid "%s (%s): %s" msgstr "" -#: src/Content/Item.php:1360 +#: src/Content/Item.php:1358 #, php-format msgid "" "Detected languages in this post:\n" @@ -2026,7 +2026,7 @@ msgstr "" #: src/Content/Nav.php:231 src/Content/Nav.php:291 #: src/Module/BaseProfile.php:70 src/Module/BaseProfile.php:73 #: src/Module/BaseProfile.php:81 src/Module/BaseProfile.php:84 -#: src/Module/Settings/Display.php:320 view/theme/frio/theme.php:223 +#: src/Module/Settings/Display.php:321 view/theme/frio/theme.php:223 #: view/theme/frio/theme.php:227 msgid "Calendar" msgstr "" @@ -2261,33 +2261,33 @@ msgstr "" msgid "last" msgstr "" -#: src/Content/Text/BBCode.php:909 +#: src/Content/Text/BBCode.php:917 #, php-format msgid "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:937 src/Model/Item.php:3622 -#: src/Model/Item.php:3628 src/Model/Item.php:3629 +#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3630 +#: src/Model/Item.php:3636 src/Model/Item.php:3637 msgid "Link to source" msgstr "" -#: src/Content/Text/BBCode.php:1727 src/Content/Text/HTML.php:901 +#: src/Content/Text/BBCode.php:1735 src/Content/Text/HTML.php:901 msgid "Click to open/close" msgstr "" -#: src/Content/Text/BBCode.php:1782 +#: src/Content/Text/BBCode.php:1790 msgid "$1 wrote:" msgstr "" -#: src/Content/Text/BBCode.php:1856 src/Content/Text/BBCode.php:1857 +#: src/Content/Text/BBCode.php:1864 src/Content/Text/BBCode.php:1865 msgid "Encrypted content" msgstr "" -#: src/Content/Text/BBCode.php:2173 +#: src/Content/Text/BBCode.php:2181 msgid "Invalid source protocol" msgstr "" -#: src/Content/Text/BBCode.php:2192 +#: src/Content/Text/BBCode.php:2200 msgid "Invalid link protocol" msgstr "" @@ -2877,37 +2877,37 @@ msgid "%s (%s)" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:421 -#: src/Module/Settings/Display.php:288 +#: src/Module/Settings/Display.php:289 msgid "Monday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:422 -#: src/Module/Settings/Display.php:289 +#: src/Module/Settings/Display.php:290 msgid "Tuesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:423 -#: src/Module/Settings/Display.php:290 +#: src/Module/Settings/Display.php:291 msgid "Wednesday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:424 -#: src/Module/Settings/Display.php:291 +#: src/Module/Settings/Display.php:292 msgid "Thursday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:425 -#: src/Module/Settings/Display.php:292 +#: src/Module/Settings/Display.php:293 msgid "Friday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:426 -#: src/Module/Settings/Display.php:293 +#: src/Module/Settings/Display.php:294 msgid "Saturday" msgstr "" #: src/Core/L10n.php:512 src/Model/Event.php:420 -#: src/Module/Settings/Display.php:287 +#: src/Module/Settings/Display.php:288 msgid "Sunday" msgstr "" @@ -3335,17 +3335,17 @@ msgid "today" msgstr "" #: src/Model/Event.php:454 src/Module/Calendar/Show.php:118 -#: src/Module/Settings/Display.php:298 src/Util/Temporal.php:343 +#: src/Module/Settings/Display.php:299 src/Util/Temporal.php:343 msgid "month" msgstr "" #: src/Model/Event.php:455 src/Module/Calendar/Show.php:119 -#: src/Module/Settings/Display.php:299 src/Util/Temporal.php:344 +#: src/Module/Settings/Display.php:300 src/Util/Temporal.php:344 msgid "week" msgstr "" #: src/Model/Event.php:456 src/Module/Calendar/Show.php:120 -#: src/Module/Settings/Display.php:300 src/Util/Temporal.php:345 +#: src/Module/Settings/Display.php:301 src/Util/Temporal.php:345 msgid "day" msgstr "" @@ -3439,44 +3439,44 @@ msgstr "" msgid "Sensitive content" msgstr "" -#: src/Model/Item.php:3522 +#: src/Model/Item.php:3530 msgid "bytes" msgstr "" -#: src/Model/Item.php:3553 +#: src/Model/Item.php:3561 #, php-format msgid "%2$s (%3$d%%, %1$d vote)" msgid_plural "%2$s (%3$d%%, %1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3555 +#: src/Model/Item.php:3563 #, php-format msgid "%2$s (%1$d vote)" msgid_plural "%2$s (%1$d votes)" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3560 +#: src/Model/Item.php:3568 #, php-format msgid "%d voter. Poll end: %s" msgid_plural "%d voters. Poll end: %s" msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3562 +#: src/Model/Item.php:3570 #, php-format msgid "%d voter." msgid_plural "%d voters." msgstr[0] "" msgstr[1] "" -#: src/Model/Item.php:3564 +#: src/Model/Item.php:3572 #, php-format msgid "Poll end: %s" msgstr "" -#: src/Model/Item.php:3605 src/Model/Item.php:3606 +#: src/Model/Item.php:3613 src/Model/Item.php:3614 msgid "View on separate page" msgstr "" @@ -3629,7 +3629,7 @@ msgstr "" msgid "Responsible account: %s" msgstr "" -#: src/Model/User.php:216 src/Model/User.php:1317 +#: src/Model/User.php:216 src/Model/User.php:1320 msgid "SERIOUS ERROR: Generation of security keys failed." msgstr "" @@ -3661,102 +3661,102 @@ msgstr "" msgid "The password can't contain white spaces nor accentuated letters" msgstr "" -#: src/Model/User.php:1199 +#: src/Model/User.php:1200 msgid "Passwords do not match. Password unchanged." msgstr "" -#: src/Model/User.php:1206 +#: src/Model/User.php:1209 msgid "An invitation is required." msgstr "" -#: src/Model/User.php:1210 +#: src/Model/User.php:1213 msgid "Invitation could not be verified." msgstr "" -#: src/Model/User.php:1218 +#: src/Model/User.php:1221 msgid "Invalid OpenID url" msgstr "" -#: src/Model/User.php:1232 src/Security/Authentication.php:231 +#: src/Model/User.php:1235 src/Security/Authentication.php:231 msgid "We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID." msgstr "" -#: src/Model/User.php:1232 src/Security/Authentication.php:231 +#: src/Model/User.php:1235 src/Security/Authentication.php:231 msgid "The error message was:" msgstr "" -#: src/Model/User.php:1238 +#: src/Model/User.php:1241 msgid "Please enter the required information." msgstr "" -#: src/Model/User.php:1252 +#: src/Model/User.php:1255 #, php-format msgid "system.username_min_length (%s) and system.username_max_length (%s) are excluding each other, swapping values." msgstr "" -#: src/Model/User.php:1259 +#: src/Model/User.php:1262 #, php-format msgid "Username should be at least %s character." msgid_plural "Username should be at least %s characters." msgstr[0] "" msgstr[1] "" -#: src/Model/User.php:1263 +#: src/Model/User.php:1266 #, php-format msgid "Username should be at most %s character." msgid_plural "Username should be at most %s characters." msgstr[0] "" msgstr[1] "" -#: src/Model/User.php:1271 +#: src/Model/User.php:1274 msgid "That doesn't appear to be your full (First Last) name." msgstr "" -#: src/Model/User.php:1276 +#: src/Model/User.php:1279 msgid "Your email domain is not among those allowed on this site." msgstr "" -#: src/Model/User.php:1280 +#: src/Model/User.php:1283 msgid "Not a valid email address." msgstr "" -#: src/Model/User.php:1283 +#: src/Model/User.php:1286 msgid "The nickname was blocked from registration by the nodes admin." msgstr "" -#: src/Model/User.php:1287 src/Model/User.php:1293 +#: src/Model/User.php:1290 src/Model/User.php:1296 msgid "Cannot use that email." msgstr "" -#: src/Model/User.php:1299 +#: src/Model/User.php:1302 msgid "Your nickname can only contain a-z, 0-9 and _." msgstr "" -#: src/Model/User.php:1307 src/Model/User.php:1357 +#: src/Model/User.php:1310 src/Model/User.php:1360 msgid "Nickname is already registered. Please choose another." msgstr "" -#: src/Model/User.php:1344 src/Model/User.php:1348 +#: src/Model/User.php:1347 src/Model/User.php:1351 msgid "An error occurred during registration. Please try again." msgstr "" -#: src/Model/User.php:1371 +#: src/Model/User.php:1374 msgid "An error occurred creating your default profile. Please try again." msgstr "" -#: src/Model/User.php:1378 +#: src/Model/User.php:1381 msgid "An error occurred creating your self contact. Please try again." msgstr "" -#: src/Model/User.php:1387 +#: src/Model/User.php:1390 msgid "An error occurred creating your default contact circle. Please try again." msgstr "" -#: src/Model/User.php:1435 +#: src/Model/User.php:1438 msgid "Profile Photos" msgstr "" -#: src/Model/User.php:1632 +#: src/Model/User.php:1636 #, php-format msgid "" "\n" @@ -3764,7 +3764,7 @@ msgid "" "\t\t\tthe administrator of %2$s has set up an account for you." msgstr "" -#: src/Model/User.php:1635 +#: src/Model/User.php:1639 #, php-format msgid "" "\n" @@ -3795,12 +3795,12 @@ msgid "" "\t\tThank you and welcome to %4$s." msgstr "" -#: src/Model/User.php:1667 src/Model/User.php:1773 +#: src/Model/User.php:1671 src/Model/User.php:1777 #, php-format msgid "Registration details for %s" msgstr "" -#: src/Model/User.php:1687 +#: src/Model/User.php:1691 #, php-format msgid "" "\n" @@ -3815,12 +3815,12 @@ msgid "" "\t\t" msgstr "" -#: src/Model/User.php:1706 +#: src/Model/User.php:1710 #, php-format msgid "Registration at %s" msgstr "" -#: src/Model/User.php:1730 +#: src/Model/User.php:1734 #, php-format msgid "" "\n" @@ -3829,7 +3829,7 @@ msgid "" "\t\t\t" msgstr "" -#: src/Model/User.php:1738 +#: src/Model/User.php:1742 #, php-format msgid "" "\n" @@ -3860,7 +3860,7 @@ msgid "" "\t\t\tThank you and welcome to %2$s." msgstr "" -#: src/Model/User.php:1800 +#: src/Model/User.php:1804 msgid "User with delegates can't be removed, please remove delegate users first" msgstr "" @@ -3884,7 +3884,7 @@ msgid "Disable" msgstr "" #: src/Module/Admin/Addons/Details.php:78 -#: src/Module/Admin/Themes/Details.php:41 src/Module/Settings/Display.php:349 +#: src/Module/Admin/Themes/Details.php:41 src/Module/Settings/Display.php:350 msgid "Enable" msgstr "" @@ -3938,7 +3938,7 @@ msgstr "" #: src/Module/Settings/Connectors.php:143 #: src/Module/Settings/Connectors.php:228 #: src/Module/Settings/ContactImport.php:110 -#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:313 +#: src/Module/Settings/Delegation.php:179 src/Module/Settings/Display.php:314 #: src/Module/Settings/Features.php:61 #: src/Module/Settings/Profile/Index.php:272 msgid "Save Settings" @@ -5920,7 +5920,7 @@ msgstr "" msgid "New Event" msgstr "" -#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:301 +#: src/Module/Calendar/Show.php:121 src/Module/Settings/Display.php:302 msgid "list" msgstr "" @@ -8400,19 +8400,19 @@ msgid "No contacts." msgstr "" #: src/Module/Profile/Conversations.php:96 src/Module/Profile/Profile.php:366 -#: src/Protocol/Feed.php:1124 +#: src/Protocol/Feed.php:1127 #, php-format msgid "%s's posts" msgstr "" #: src/Module/Profile/Conversations.php:97 src/Module/Profile/Profile.php:367 -#: src/Protocol/Feed.php:1127 +#: src/Protocol/Feed.php:1130 #, php-format msgid "%s's comments" msgstr "" #: src/Module/Profile/Conversations.php:98 src/Module/Profile/Profile.php:368 -#: src/Protocol/Feed.php:1120 +#: src/Protocol/Feed.php:1123 #, php-format msgid "%s's timeline" msgstr "" @@ -9382,12 +9382,12 @@ msgid "When selected, the channel results are reshared. This only works for publ msgstr "" #: src/Module/Settings/Channels.php:176 src/Module/Settings/Channels.php:202 -#: src/Module/Settings/Display.php:347 +#: src/Module/Settings/Display.php:348 msgid "Label" msgstr "" #: src/Module/Settings/Channels.php:177 src/Module/Settings/Channels.php:203 -#: src/Module/Settings/Display.php:348 +#: src/Module/Settings/Display.php:349 #: src/Module/Settings/TwoFactor/AppSpecific.php:123 msgid "Description" msgstr "" @@ -9815,193 +9815,197 @@ msgstr "" msgid "Large Image" msgstr "" -#: src/Module/Settings/Display.php:312 +#: src/Module/Settings/Display.php:268 +msgid "Automatic image size" +msgstr "" + +#: src/Module/Settings/Display.php:313 msgid "Display Settings" msgstr "" -#: src/Module/Settings/Display.php:314 +#: src/Module/Settings/Display.php:315 msgid "General Theme Settings" msgstr "" -#: src/Module/Settings/Display.php:315 +#: src/Module/Settings/Display.php:316 msgid "Custom Theme Settings" msgstr "" -#: src/Module/Settings/Display.php:316 +#: src/Module/Settings/Display.php:317 msgid "Content Settings" msgstr "" -#: src/Module/Settings/Display.php:317 view/theme/duepuntozero/config.php:74 +#: src/Module/Settings/Display.php:318 view/theme/duepuntozero/config.php:74 #: view/theme/frio/config.php:156 view/theme/quattro/config.php:76 #: view/theme/vier/config.php:124 msgid "Theme settings" msgstr "" -#: src/Module/Settings/Display.php:318 +#: src/Module/Settings/Display.php:319 msgid "Timelines" msgstr "" -#: src/Module/Settings/Display.php:325 +#: src/Module/Settings/Display.php:326 msgid "Display Theme:" msgstr "" -#: src/Module/Settings/Display.php:326 +#: src/Module/Settings/Display.php:327 msgid "Mobile Theme:" msgstr "" -#: src/Module/Settings/Display.php:329 +#: src/Module/Settings/Display.php:330 msgid "Number of items to display per page:" msgstr "" -#: src/Module/Settings/Display.php:329 src/Module/Settings/Display.php:330 +#: src/Module/Settings/Display.php:330 src/Module/Settings/Display.php:331 msgid "Maximum of 100 items" msgstr "" -#: src/Module/Settings/Display.php:330 +#: src/Module/Settings/Display.php:331 msgid "Number of items to display per page when viewed from mobile device:" msgstr "" -#: src/Module/Settings/Display.php:331 +#: src/Module/Settings/Display.php:332 msgid "Regularly update the page content" msgstr "" -#: src/Module/Settings/Display.php:331 +#: src/Module/Settings/Display.php:332 msgid "When enabled, new content on network, community and channels are added on top." msgstr "" -#: src/Module/Settings/Display.php:332 +#: src/Module/Settings/Display.php:333 msgid "Display emoticons" msgstr "" -#: src/Module/Settings/Display.php:332 +#: src/Module/Settings/Display.php:333 msgid "When enabled, emoticons are replaced with matching symbols." msgstr "" -#: src/Module/Settings/Display.php:333 +#: src/Module/Settings/Display.php:334 msgid "Infinite scroll" msgstr "" -#: src/Module/Settings/Display.php:333 +#: src/Module/Settings/Display.php:334 msgid "Automatic fetch new items when reaching the page end." msgstr "" -#: src/Module/Settings/Display.php:334 +#: src/Module/Settings/Display.php:335 msgid "Enable Smart Threading" msgstr "" -#: src/Module/Settings/Display.php:334 +#: src/Module/Settings/Display.php:335 msgid "Enable the automatic suppression of extraneous thread indentation." msgstr "" -#: src/Module/Settings/Display.php:335 +#: src/Module/Settings/Display.php:336 msgid "Display the Dislike feature" msgstr "" -#: src/Module/Settings/Display.php:335 +#: src/Module/Settings/Display.php:336 msgid "Display the Dislike button and dislike reactions on posts and comments." msgstr "" -#: src/Module/Settings/Display.php:336 +#: src/Module/Settings/Display.php:337 msgid "Display the resharer" msgstr "" -#: src/Module/Settings/Display.php:336 +#: src/Module/Settings/Display.php:337 msgid "Display the first resharer as icon and text on a reshared item." msgstr "" -#: src/Module/Settings/Display.php:337 +#: src/Module/Settings/Display.php:338 msgid "Stay local" msgstr "" -#: src/Module/Settings/Display.php:337 +#: src/Module/Settings/Display.php:338 msgid "Don't go to a remote system when following a contact link." msgstr "" -#: src/Module/Settings/Display.php:338 +#: src/Module/Settings/Display.php:339 msgid "Show the post deletion checkbox" msgstr "" -#: src/Module/Settings/Display.php:338 +#: src/Module/Settings/Display.php:339 msgid "Display the checkbox for the post deletion on the network page." msgstr "" -#: src/Module/Settings/Display.php:339 +#: src/Module/Settings/Display.php:340 msgid "DIsplay the event list" msgstr "" -#: src/Module/Settings/Display.php:339 +#: src/Module/Settings/Display.php:340 msgid "Display the birthday reminder and event list on the network page." msgstr "" -#: src/Module/Settings/Display.php:340 +#: src/Module/Settings/Display.php:341 msgid "Link preview mode" msgstr "" -#: src/Module/Settings/Display.php:340 +#: src/Module/Settings/Display.php:341 msgid "Appearance of the link preview that is added to each post with a link." msgstr "" -#: src/Module/Settings/Display.php:341 +#: src/Module/Settings/Display.php:342 msgid "Hide pictures with empty alternative text" msgstr "" -#: src/Module/Settings/Display.php:341 +#: src/Module/Settings/Display.php:342 msgid "Don't display pictures that are missing the alternative text." msgstr "" -#: src/Module/Settings/Display.php:342 +#: src/Module/Settings/Display.php:343 msgid "Hide custom emojis" msgstr "" -#: src/Module/Settings/Display.php:342 +#: src/Module/Settings/Display.php:343 msgid "Don't display custom emojis." msgstr "" -#: src/Module/Settings/Display.php:343 +#: src/Module/Settings/Display.php:344 msgid "Platform icons style" msgstr "" -#: src/Module/Settings/Display.php:343 +#: src/Module/Settings/Display.php:344 msgid "Style of the platform icons" msgstr "" -#: src/Module/Settings/Display.php:344 +#: src/Module/Settings/Display.php:345 msgid "Embed remote media" msgstr "" -#: src/Module/Settings/Display.php:344 +#: src/Module/Settings/Display.php:345 msgid "When enabled, remote media will be embedded in the post, like for example YouTube videos." msgstr "" -#: src/Module/Settings/Display.php:345 +#: src/Module/Settings/Display.php:346 msgid "Embed supported media" msgstr "" -#: src/Module/Settings/Display.php:345 +#: src/Module/Settings/Display.php:346 msgid "When enabled, remote media will be embedded in the post instead of using the local player if this is supported by the remote system. This is useful for media where the remote player is better than the local one, like for example Peertube videos." msgstr "" -#: src/Module/Settings/Display.php:350 +#: src/Module/Settings/Display.php:351 msgid "Bookmark" msgstr "" -#: src/Module/Settings/Display.php:352 +#: src/Module/Settings/Display.php:353 msgid "Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu." msgstr "" -#: src/Module/Settings/Display.php:354 +#: src/Module/Settings/Display.php:355 msgid "Channel languages:" msgstr "" -#: src/Module/Settings/Display.php:354 +#: src/Module/Settings/Display.php:355 msgid "Select all the languages you want to see in your channels. \"Unspecified\" describes all posts for which no language information was detected (e.g. posts with just an image or too little text to be sure of the language). If you want to see all languages, you will need to select all items in the list." msgstr "" -#: src/Module/Settings/Display.php:356 +#: src/Module/Settings/Display.php:357 msgid "Beginning of week:" msgstr "" -#: src/Module/Settings/Display.php:357 +#: src/Module/Settings/Display.php:358 msgid "Default calendar view:" msgstr "" From 1d5ff8389fb3a14a955ddfd8fa25ad5a5ed4a5ce Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 6 Oct 2025 02:30:06 +0000 Subject: [PATCH 021/138] Possibility to use Video.js as alternate video player --- REUSE.toml | 5 ++ src/Content/Post/Repository/PostMedia.php | 9 +++- static/defaults.config.php | 4 ++ view/js/videojs/video-js.min.css | 1 + view/js/videojs/video.min.js | 53 +++++++++++++++++++ .../{hls_top.tpl => content/hls.tpl} | 2 +- .../{video_top.tpl => content/video.tpl} | 2 +- view/templates/content/videojs.tpl | 37 +++++++++++++ view/templates/oembed_video.tpl | 10 ---- view/templates/videos_head.tpl | 6 --- view/templates/videos_recent.tpl | 17 ------ view/theme/frio/css/style.css | 1 + view/theme/vier/style.css | 1 + 13 files changed, 111 insertions(+), 37 deletions(-) create mode 100644 view/js/videojs/video-js.min.css create mode 100644 view/js/videojs/video.min.js rename view/templates/{hls_top.tpl => content/hls.tpl} (96%) rename view/templates/{video_top.tpl => content/video.tpl} (95%) create mode 100644 view/templates/content/videojs.tpl delete mode 100644 view/templates/oembed_video.tpl delete mode 100644 view/templates/videos_head.tpl delete mode 100644 view/templates/videos_recent.tpl diff --git a/REUSE.toml b/REUSE.toml index b7e959535b..8f305ad303 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -260,6 +260,11 @@ path = "view/js/hls/**" SPDX-FileCopyrightText = "2017 Dailymotion (http://www.dailymotion.com)" SPDX-License-Identifier = "Apache-2.0" +[[annotations]] +path = "view/js/videojs/**" +SPDX-FileCopyrightText = "Copyright 2010-present Video.js contributors" +SPDX-License-Identifier = "Apache-2.0" + [[annotations]] path = [ "images/rm-16.png", "images/rhash-16.png"] SPDX-FileCopyrightText = "Red Matrix Project" diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index 5c71d9bad0..dedcb3352b 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -415,8 +415,12 @@ class PostMedia extends BaseRepository } elseif ($this->pConfig->get($uid, 'system', 'embed_media', false) && $postMedia->hasEmbedHtml() && !$postMedia->isPhoto()) { $media = $this->getEmbedIframe($postMedia); } else { - /// @todo Move the template to /content as well - $media = Renderer::replaceMacros(Renderer::getMarkupTemplate($postMedia->type == Post\Media::HLS ? 'hls_top.tpl' : 'video_top.tpl'), [ + if ($this->config->get('system', 'videojs')) { + $template = 'content/videojs.tpl'; + } else { + $template = $postMedia->type == Post\Media::HLS ? 'content/hls.tpl' : 'content/video.tpl'; + } + $media = Renderer::replaceMacros(Renderer::getMarkupTemplate($template), [ '$video' => [ 'id' => $postMedia->id, 'src' => (string)$postMedia->url, @@ -425,6 +429,7 @@ class PostMedia extends BaseRepository 'mime' => (string)$postMedia->mimetype, 'height' => $height, 'width' => $width, + 'style' => 'aspect-ratio:' . $postMedia->width . '/' . $postMedia->height . ';', 'description' => $postMedia->description, ], ]); diff --git a/static/defaults.config.php b/static/defaults.config.php index 94a1a12176..68dc1b510b 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -613,6 +613,10 @@ return [ // Minimum for this config value is 1. Maximum is 64 as the resulting profile URL mustn't be longer than 255 chars. 'username_max_length' => 48, + // videojs (Boolean) + // Experimental: Use Video.js as videoplayer. Since there are known issues, enabling is not recommended. + 'videojs' => false, + // worker_cooldown (Float) // Cooldown period in seconds before each worker function call. 'worker_cooldown' => 0, diff --git a/view/js/videojs/video-js.min.css b/view/js/videojs/video-js.min.css new file mode 100644 index 0000000000..3194559e10 --- /dev/null +++ b/view/js/videojs/video-js.min.css @@ -0,0 +1 @@ +.vjs-svg-icon{display:inline-block;background-repeat:no-repeat;background-position:center;fill:currentColor;height:1.8em;width:1.8em}.vjs-svg-icon:before{content:none!important}.vjs-control:focus .vjs-svg-icon,.vjs-svg-icon:hover{filter:drop-shadow(0 0 .25em #fff)}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-modal-dialog,.vjs-button>.vjs-icon-placeholder:before,.vjs-modal-dialog .vjs-modal-dialog-content{position:absolute;top:0;left:0;width:100%;height:100%}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.vjs-button>.vjs-icon-placeholder:before{text-align:center}@font-face{font-family:VideoJS;src:url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAABTsAAsAAAAAIpAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAPgAAAFZRiV32Y21hcAAAAYQAAAEJAAAD5p42+VxnbHlmAAACkAAADtIAABckI4l972hlYWQAABFkAAAAKwAAADYsvIjpaGhlYQAAEZAAAAAdAAAAJA+RCL1obXR4AAARsAAAABcAAAC8Q2YAAGxvY2EAABHIAAAAYAAAAGB7CIGGbWF4cAAAEigAAAAfAAAAIAFAAI9uYW1lAAASSAAAASUAAAIK1cf1oHBvc3QAABNwAAABfAAAAnXdFqh1eJxjYGRgYOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBmg4gCACY7BUgAeJxjYGR7yDiBgZWBgaWQ5RkDA8MvCM0cwxDOeI6BgYmBlZkBKwhIc01hcPjI+FGPHcRdyA4RZgQRADaGCyYAAHic7dPXbcMwAEXRK1vuvffem749XAbKV3bjBA6fXsaIgMMLEWoQJaAEFKNnlELyQ4K27zib5PNF6vl8yld+TKr5kH0+cUw0xv00Hwvx2DResUyFKrV4XoMmLdp06NKjz4AhI8ZMmDJjzoIlK9Zs2LJjz4EjJ85cuHLjziPe/0UWL17mf2tqKLz/9jK9f8tXpGCoRdPKhtS0RqFkWvVQNtSKoVYNtWaoddPXEBqG2jQ9XWgZattQO4baNdSeofYNdWCoQ0MdGerYUCeGOjXUmaHODXVhqEtDXRnq2lA3hro11J2h7g31YKhHQz0Z6tlQL4Z6NdSbod4N9WGoT9MfHF6GmhnZLxyDcRMAAAB4nJ1YC1hU17U+a5/HMA4iA3NmVBDmoQwP5TFnHlFeA4gYiUFRQINoSCBAyK3G2yi+0aipYtFcHYo2xsb4NiY3+VrNxSaX5uvt495ozNdoYoxmem2/L8HGpLc+InB279pnhlGr5mvL4eyz99nrrL32eu1/DQcc/okdYgdHOA6MQKp4r9gx0EcMHMezOalVasW5BM7NcXoSb9fFgE6KtSSBxWz1FYDPG+vMBGcKb9cebu2VS5s2aaTkCvRSf6C7Y+Ppibm5E09v7IDs2/3uZQtbD0zIyppwoHXh/93ukmyYgdePNRp65p5v+3v/9otQl2O7wP34cT88p8Md2YxpYLQZoRcy6FlSBRnwnGAe6BPMSCZo+7NJVqS0cE4uHendzhSnbPH6TDqL1+Nme5LZXkCHnGyoH0kne30WH+gswhm3q+pt/mTas9NLS64GnjmSlTPw0wVQT/ewRaBgxtydy3cuUB9/6SW+vb5yRvr+t0eOfPKJZ/9t3+4tL7xj32Xd3thCxi+ge6ifdsAN+l5+wi5HQ/cCoeull1AszS7CUfEcJzK7sKWJAdJhCd0sPM4+EY7QDm5ov08hXRQXE5bf6PV5Q5+IjW7X7Nku92Ask4l2hCRRD6TPqISiCJeQna3SCFwrhrNzXHzo4yFevBwxpzxk8WCIIfkvVEKVy32SbT8n68gzgaslpaiO2zIGIyuSb7RNf9HSuN26y/7OC1tgEmpiyA6aD4qcgTOiLThwGG0eB694FI8NHLLN6OBlRVaMxNAFS4JdXUG6mW8PwpKuYLCLXKGbu8iwYNdgO06Sn3Th+/vyZAxs8Ro30DjHe9gy8Fywi24OMm7Qyzh3MTZVOMYhLBnoC+J79lpTUyQmorjhnMwlcQ5uPEYGpDjsOkkH49BjQLQBqs3jFtFdJNlksYmoQFDArLh8Xh+Qd6Ghcsb6FUuehDi+U/lqD71K/qiegeV1imcwjl7ExwiSrf4BZyCujV6cVcFo6VX+G9IcPyFjJnUufbU/jzrL1X99as36reXl8K32nFaOr+E8jWJEcJ55DpMVfSMe95/AJaOsGBH2GJCNpiRQbK4C8BjdmQA22QY2j03Em13i2YHqtNLU1NI04Yj2HJgA6fQc6VPNpA/D+Ryks554NnVy2mB72uRUfPLsqR4N0LOBQKArwJYO+5W2fgZX8oC1HR6HjNaQTVIG2FPwnTcXXGZZfNB7TE6pTKZUwaw91XWLAoFFGcnB5PHjsckgBjbWutrL+0h5Y1xw3DRGDumsnXb3MJwXrJIN5U7m0rgJ3yG5w4he5ckFG4pmNEkOm0/xOO4r4yL87wqtQM+hiJIVp+6iG2wPBKD35ElGkDx+UfC2v1mFG1o+M3AjNFty8biKMXwzyxnZLds8wYD2BxmCPHAldPOeLsy/0BugftYhVYFAhO8SqQ0j3oK7dHJZnI/jxmUS4onlxskSF8thmvNZjIrRZwEPxr0lBuLRuz3oy/FOHCsxwOPYh2M+e9u3J5pgPYz9gp6G7C9m0A11F9ddqKMfV+4sbq45/YspOysXvT+3pdFdYNg2fHbW8Dz301MqDVuGrz0Fuh0YMW8mddrpqzST7rV9BcvqPoNvadRndWp0p8HvbiqrFj5yFQ/vNFSXDpxpLEFWp+DcrF3FT1afWshFcmCfeAMjEvO65i0Y6XijQfSRPWx3TV/Df7Km3E1l+kLt56s/rwVzuRusNMhudznkwdLaS+QNdeal2jDPP4l9qHc98vTYZOSkxzD+njBWVWjFPKgipx6DkWvXQiW8OYcewVHE5yukinDMcfGgc0opDltYKDxIGBedkzc6jSfE7tlvESCDFUw0Hx0opS+U0lHCxNottbNWSxX9zZVvEhKWUSyBpaXwBc2a98M6UqPeXAs/GDon8Ax7hsthO8cM5HU7Ad0UvRR9lHmtyQKZ4MAe814X5h9MSUkQmhf96eVJ6p90OjIiqSIjvykvr2l5U55O/fPQKD+jIomYpNyGJQ25uQ2kIikRfAmuBHCPsWqkSDEqgZ5KDI2sifS/R43MbZg0idFHbCPNxXxZws1ACVE6hAhOdJwRkJLFBLPZpRGYJ50pko6XzMkgmSx40ljik6AQcKhFnLcQE6rF7PXFe1Ocoj0T3AXgSgJTDIhHRfHlYZKuSzc6uievOJGXY+i5GJkkTp7UM3y0LqATDbtFcbdBxO7o4T25JYlEjoH0uynUh8rapkxp62QN70svSF+hT4gGPlovlmcm/ComLi7mV4kTykV9NFWjE/QrwgQ4uIcAP0rQF4VZYRP2o3PhHHzfPMJj9Ir+uzKUlrH49ntT18AVvj1sc3YGjUT/Mt2Dxawa8ArcA7bCQIpvfwAYu22vEG/No/5RvPdA7g+AelLrPwzy+LtkLPhnpIxH14m4EYq8eeMHbPEPNm6G7Nv9B4jcFPZ8bJj0SEjP3MPgQdKTqqEoy2v6G32P/Y6dxOv04AxnoAeq+GILvUavtYCBXm+BaIhuodcfrN5B/V2EYMCPh+SxavjGyPwV0x4CJgUPGT0mQaODGBACIJZGsMXwAD0LGXx7l3CdAcKMIKI+f5CepWeD0BvyU/GcdBxPF8SwejC6LGZmAURFdsSWKR5HyHld2kbdIZO1Ixx+bnnzU7n5+blPNV9jnUDWhP2tC68tbN3PVIldsQPxSAcSpjOav7Q05uXn5zW2LLvDXn9B6syscPy9iDLEMmSrJz6nYuWMipukjM0AH8JkGS+XFyMRkzSCH7KD/hwm172SAyZYumHlefr5AddrtA0O0TnwaVZxcRY9Bfukn9Gf05N1r9DV9MoBsJ1f+ZrqUvtPHizJAntWybv7hmqLt6QLuK6ZS9Fqi1jO5rDoWPZXXII5Tgajg53cIXCjDCGIcYrRIY2n6+mXOa/W0bdhau3ryiEYe2FV/5oeaIYK/5w5frCyll6/cYO8DiNhw6t1MBWmznt91QX62UF1N7l0eHBZTRGpKaqpKVIPF9UcIzmReud9TSY75+K899GHbBu6wjoR7RKKZVYiYxSPf5/2wJT5e3NAhmUbVn5KLx1Ujg0+BGvpAIh0DezInTkzF37KVocxrKU3r1+XLtAe2lO3l66kfQfB/unKY+q8N375Ru8bc4pJXfEcESU95q+p8ZNZRTWH1d9FzvUdYXk5rLkcdkEisoKKVHQW/b3GEx6tPaYcoJfOr9wAbSBnv1IHpep0OExr4LPMkpJM+j7sly7UHkOzXjoAZljHCGiyegtNlwljM0v+c19ET9Pvst09a2Mtgcf5/ZSzYO5h1156+eyydfAsxGa9XAuF6vzjh6CssLq6ECysperXX0sX5h5ZdpZe3guxsGIPEtHk/aqXX1hVqP5HYVVVISkrrNqvXorIc+5Ou91Hnr/LcD2afi6eX7UBloOcs7cOpqgGaNfs1g7bNbs9z6wASaylN69d0/TFTIz6Ws8+oGV3mE2612wRTHKcVUbhjKadebloMc+dyXgMVtVK6BwMB/+mVW09igdRBWaRtNQX59d/VD//xdQ0TCiYNj1KT9sq6Wdu5WTbqk3qDXyDaLa1fv621LS01G3z61sD6lH8lAxDLicV921s6Bf92JOYvzNYCL1khbqBXEFUzC521N5NyzNaQIWhjyFyDoBIVrAjmv2UEaLlI+c6zw1jmVIPLLLZZUTj6GxGHW+mq1tgHXR2D85p4Q934+jLbtjVLcyCdS10NVzpHqxp4Q/hK7WopY/NRGx9HGsPGdFjOjcpjBnGYMVqY/4eqT5khWEHWUup2A/pTw7pdWgsWft7ETUERL96nRg0HNFPmCYba6pylECaExX89A9WLUOVB4oKLu/o1oqSYHCgLzBUlAz8hNFDRpeSU1XT+LRmDUgPaKbYdHDn9suF/tu13nHJij0N97LfS0QmqONuyONk7zvUI6Qa0pF9f2+oABL92AT6e0U//z9YqAiWtJLU1JK0gS+1aacwamiNqK067u9ZQ8f1d4qLodMzz3uL89Z68V/Hnr++hXWUuHgw8dfi972PeTyPefu3aNNucemQ74qFuIaJnVkOu4Q+yjuwmmC1FqZpl1i4uzoPxjkpPf3Xv545tl26Rr+dOvUd+omqJzch9dOeU7f10Y64nMcKK137DccIZq2WdXtdZjbEoLSzHwiMtrjYLDxpHQW8gjMX6XFYAE2zSWVD04EGYSs9MbO6sEo20BMEAB4mpvSypsKjZ4Stgzb+c3A9/MQT2+vrBy+qvyFxLUtLlSRF/Ri2wjfZ2dus2Q8lXx4608/jnqK5OOap6NY2PSjYYnECCjiEeLJll/pbmqfeIK+ps3+MxrlEhqmTPipVP7kqlF4VhpEb6r+Q7YOJg38kJ9SHBf3NBl6+9YchfbUjb5ahLSzUM3kPHmwFAsZ5rpai0S7E5xWzZ1j+fW7zsUWP2g5NXTw52ySCTrgG0+lbw60l2Y/CB185CoA8NK+tbRKxfjy6pm5hzQRRR+cMqv1Jbiw6STivtEvt3DRcy0QEh92JlUGo2PG4tSKHl00YD6xc8CK+YPYyy3io2lN8BcSjKRzrIV6ypOAobqxViJPaT9M9Hy5szY33mp7OX/Zu89L/7Ww5vqY2Y8b0pKgoiUhG5cPDPzq8qTV/WkzUOIvXVVA96kmjcBrr3HrYC/Wn+fYP6Z7T1rqy3zknbvqma/FvVk96fNXGkuaXrdHW5JGSxZT/2I/O73v+yNWafMdzc5NdxYurHs6h86e01sLKLz9EBrg+x36rxAaED7hRnAMx7Vzu+9wabh3zG8XLQjx0ablUJzmxdErxYT3kzQSd0SSafVqF5PXgpp0OyYJ1EyNHpGUZmvK575ySzd85JSqF7IBzSAbMM04+MbE58xF3/njXOGecSaermlw2y9PsSQdytLJVr8t+wg+rR8cZYoeNxVIzNdk3Bngi8U5LAlgTFoQnzJCa5EsCgYhCaGL+qPj7TdhG31p9tej3R04N//PXxNwJvyUqwaJqRPJY98TJ5TPndmflRAkAhBfe46sfKW5wizSge08Xb7Ca/GUVs55trngkKkrUS2WPzKttaaqq+idmahugkY+W6fN0I6i3gPt/x88U4wAAeJxjYGRgYADiGU9YXsXz23xl4GZnAIFH7fO+IdMc/WBxDgYmEAUASbMKwAB4nGNgZGBgZwABjj4Ghv//OfoZGBlQgT4ARicDZAAAAHicY2BgYGAfxJijD8Fmu4EqBwCSpgKpAAAAAAAADgBoAH4AzADgAQIBQgFsAZgB7gIuAooC0AL8A2IDjAOoA+AEMASwBNoFCAVaBcAGCAYuBnAGrAb2B04HigfSCCoIcAiGCJwIyAkkCVYJiAmsCfIKIApWCsQLknicY2BkYGDQZ2hmYGcAASYg5gJCBob/YD4DABqrAdAAeJxdkE1qg0AYhl8Tk9AIoVDaVSmzahcF87PMARLIMoFAl0ZHY1BHdBJIT9AT9AQ9RQ9Qeqy+yteNMzDzfM+88w0K4BY/cNAMB6N2bUaPPBLukybCLvleeAAPj8JD+hfhMV7hC3u4wxs7OO4NzQSZcI/8Ltwnfwi75E/hAR7wJTyk/xYeY49fYQ/PztM+jbTZ7LY6OWdBJdX/pqs6NYWa+zMxa13oKrA6Uoerqi/JwtpYxZXJ1coUVmeZUWVlTjq0/tHacjmdxuL90OR8O0UEDYMNdtiSEpz5XQGqzlm30kzUdAYFFOb8R7NOZk0q2lwAyz1i7oAr1xoXvrOgtYhZx8wY5KRV269JZ5yGpmzPTjQhvY9je6vEElPOuJP3mWKnP5M3V+YAAAB4nG2ReVPbMBDF/ULi2EkDBFqO3gdHLxUzDB9IkdexBllydRD49ihO3Ckz7B/a31utZnafkkGyiXnyclxhgB0MMUKKMTLkmGCKV5hhF3vYxxwHOMRrvMERjnGCU7zFO7zHB3zEJ3zGF3zFN5zhHBe4xHf8wE/8wm8w/MEVimTYKv44XR9MSCsUjVoeHE3vjQoNsSZ4mmxZmVWPjSz7jlou6/0qKOWEJdKMtCe793/hQfqxa6XWZHMXFl56RS4TvPXSaDeoy0zUUZB109KstDK8lHo5q6Qi1hcOnqkImubPS6aqRq7mlnaEWabub4iYblba3SRmgldS0+FWdhNtt04F14JUaqkl7tcpOpJtErvNt3Bd9HRT5JWxK25Ldjvp6br4hzfFiIdSmlzTg2fSUzNrLd1LE1ynxq4OVaVoKLjzJ60UPtj1RKzHzsbjly6inVnFBS2MucviPncU7Rr7lfTxRepDs1A2j3ZHRc7PuzFYSfE3ZOd4kjwBy227hA==) format("woff");font-weight:400;font-style:normal}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-play-control .vjs-icon-placeholder,.vjs-icon-play{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-play-control .vjs-icon-placeholder:before,.vjs-icon-play:before{content:"\f101"}.vjs-icon-play-circle{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-play-circle:before{content:"\f102"}.video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder,.vjs-icon-pause{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder:before,.vjs-icon-pause:before{content:"\f103"}.video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder,.vjs-icon-volume-mute{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder:before,.vjs-icon-volume-mute:before{content:"\f104"}.video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder,.vjs-icon-volume-low{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder:before,.vjs-icon-volume-low:before{content:"\f105"}.video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder,.vjs-icon-volume-mid{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder:before,.vjs-icon-volume-mid:before{content:"\f106"}.video-js .vjs-mute-control .vjs-icon-placeholder,.vjs-icon-volume-high{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control .vjs-icon-placeholder:before,.vjs-icon-volume-high:before{content:"\f107"}.video-js .vjs-fullscreen-control .vjs-icon-placeholder,.vjs-icon-fullscreen-enter{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-fullscreen-control .vjs-icon-placeholder:before,.vjs-icon-fullscreen-enter:before{content:"\f108"}.video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder,.vjs-icon-fullscreen-exit{font-family:VideoJS;font-weight:400;font-style:normal}.video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder:before,.vjs-icon-fullscreen-exit:before{content:"\f109"}.vjs-icon-spinner{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-spinner:before{content:"\f10a"}.video-js .vjs-subs-caps-button .vjs-icon-placeholder,.video-js .vjs-subtitles-button .vjs-icon-placeholder,.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder,.vjs-icon-subtitles{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js .vjs-subtitles-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder:before,.vjs-icon-subtitles:before{content:"\f10b"}.video-js .vjs-captions-button .vjs-icon-placeholder,.video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder,.vjs-icon-captions{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-captions-button .vjs-icon-placeholder:before,.video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder:before,.vjs-icon-captions:before{content:"\f10c"}.vjs-icon-hd{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-hd:before{content:"\f10d"}.video-js .vjs-chapters-button .vjs-icon-placeholder,.vjs-icon-chapters{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-chapters-button .vjs-icon-placeholder:before,.vjs-icon-chapters:before{content:"\f10e"}.vjs-icon-downloading{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-downloading:before{content:"\f10f"}.vjs-icon-file-download{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-file-download:before{content:"\f110"}.vjs-icon-file-download-done{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-file-download-done:before{content:"\f111"}.vjs-icon-file-download-off{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-file-download-off:before{content:"\f112"}.vjs-icon-share{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-share:before{content:"\f113"}.vjs-icon-cog{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-cog:before{content:"\f114"}.vjs-icon-square{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-square:before{content:"\f115"}.video-js .vjs-play-progress,.video-js .vjs-volume-level,.vjs-icon-circle,.vjs-seek-to-live-control .vjs-icon-placeholder{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-progress:before,.video-js .vjs-volume-level:before,.vjs-icon-circle:before,.vjs-seek-to-live-control .vjs-icon-placeholder:before{content:"\f116"}.vjs-icon-circle-outline{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-circle-outline:before{content:"\f117"}.vjs-icon-circle-inner-circle{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-circle-inner-circle:before{content:"\f118"}.video-js .vjs-control.vjs-close-button .vjs-icon-placeholder,.vjs-icon-cancel{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-control.vjs-close-button .vjs-icon-placeholder:before,.vjs-icon-cancel:before{content:"\f119"}.vjs-icon-repeat{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-repeat:before{content:"\f11a"}.video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder,.vjs-icon-replay{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder:before,.vjs-icon-replay:before{content:"\f11b"}.video-js .vjs-skip-backward-5 .vjs-icon-placeholder,.vjs-icon-replay-5{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-backward-5 .vjs-icon-placeholder:before,.vjs-icon-replay-5:before{content:"\f11c"}.video-js .vjs-skip-backward-10 .vjs-icon-placeholder,.vjs-icon-replay-10{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-backward-10 .vjs-icon-placeholder:before,.vjs-icon-replay-10:before{content:"\f11d"}.video-js .vjs-skip-backward-30 .vjs-icon-placeholder,.vjs-icon-replay-30{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-backward-30 .vjs-icon-placeholder:before,.vjs-icon-replay-30:before{content:"\f11e"}.video-js .vjs-skip-forward-5 .vjs-icon-placeholder,.vjs-icon-forward-5{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-forward-5 .vjs-icon-placeholder:before,.vjs-icon-forward-5:before{content:"\f11f"}.video-js .vjs-skip-forward-10 .vjs-icon-placeholder,.vjs-icon-forward-10{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-forward-10 .vjs-icon-placeholder:before,.vjs-icon-forward-10:before{content:"\f120"}.video-js .vjs-skip-forward-30 .vjs-icon-placeholder,.vjs-icon-forward-30{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-skip-forward-30 .vjs-icon-placeholder:before,.vjs-icon-forward-30:before{content:"\f121"}.video-js .vjs-audio-button .vjs-icon-placeholder,.vjs-icon-audio{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-audio-button .vjs-icon-placeholder:before,.vjs-icon-audio:before{content:"\f122"}.vjs-icon-next-item{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-next-item:before{content:"\f123"}.vjs-icon-previous-item{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-previous-item:before{content:"\f124"}.vjs-icon-shuffle{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-shuffle:before{content:"\f125"}.vjs-icon-cast{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-cast:before{content:"\f126"}.video-js .vjs-picture-in-picture-control .vjs-icon-placeholder,.vjs-icon-picture-in-picture-enter{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-picture-in-picture-control .vjs-icon-placeholder:before,.vjs-icon-picture-in-picture-enter:before{content:"\f127"}.video-js.vjs-picture-in-picture .vjs-picture-in-picture-control .vjs-icon-placeholder,.vjs-icon-picture-in-picture-exit{font-family:VideoJS;font-weight:400;font-style:normal}.video-js.vjs-picture-in-picture .vjs-picture-in-picture-control .vjs-icon-placeholder:before,.vjs-icon-picture-in-picture-exit:before{content:"\f128"}.vjs-icon-facebook{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-facebook:before{content:"\f129"}.vjs-icon-linkedin{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-linkedin:before{content:"\f12a"}.vjs-icon-twitter{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-twitter:before{content:"\f12b"}.vjs-icon-tumblr{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-tumblr:before{content:"\f12c"}.vjs-icon-pinterest{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-pinterest:before{content:"\f12d"}.video-js .vjs-descriptions-button .vjs-icon-placeholder,.vjs-icon-audio-description{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-descriptions-button .vjs-icon-placeholder:before,.vjs-icon-audio-description:before{content:"\f12e"}.video-js{display:inline-block;vertical-align:top;box-sizing:border-box;color:#fff;background-color:#000;position:relative;padding:0;font-size:10px;line-height:1;font-weight:400;font-style:normal;font-family:Arial,Helvetica,sans-serif;word-break:initial}.video-js:-moz-full-screen{position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.video-js[tabindex="-1"]{outline:0}.video-js *,.video-js :after,.video-js :before{box-sizing:inherit}.video-js ul{font-family:inherit;font-size:inherit;line-height:inherit;list-style-position:outside;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}.video-js.vjs-1-1,.video-js.vjs-16-9,.video-js.vjs-4-3,.video-js.vjs-9-16,.video-js.vjs-fluid{width:100%;max-width:100%}.video-js.vjs-1-1:not(.vjs-audio-only-mode),.video-js.vjs-16-9:not(.vjs-audio-only-mode),.video-js.vjs-4-3:not(.vjs-audio-only-mode),.video-js.vjs-9-16:not(.vjs-audio-only-mode),.video-js.vjs-fluid:not(.vjs-audio-only-mode){height:0}.video-js.vjs-16-9:not(.vjs-audio-only-mode){padding-top:56.25%}.video-js.vjs-4-3:not(.vjs-audio-only-mode){padding-top:75%}.video-js.vjs-9-16:not(.vjs-audio-only-mode){padding-top:177.7777777778%}.video-js.vjs-1-1:not(.vjs-audio-only-mode){padding-top:100%}.video-js.vjs-fill:not(.vjs-audio-only-mode){width:100%;height:100%}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}.video-js.vjs-audio-only-mode .vjs-tech{display:none}body.vjs-full-window,body.vjs-pip-window{padding:0;margin:0;height:100%}.vjs-full-window .video-js.vjs-fullscreen,body.vjs-pip-window .video-js{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0}.video-js.vjs-fullscreen:not(.vjs-ios-native-fs),body.vjs-pip-window .video-js{width:100%!important;height:100%!important;padding-top:0!important;display:block}.video-js.vjs-fullscreen.vjs-user-inactive{cursor:none}.vjs-pip-container .vjs-pip-text{position:absolute;bottom:10%;font-size:2em;background-color:rgba(0,0,0,.7);padding:.5em;text-align:center;width:100%}.vjs-layout-small.vjs-pip-container .vjs-pip-text,.vjs-layout-tiny.vjs-pip-container .vjs-pip-text,.vjs-layout-x-small.vjs-pip-container .vjs-pip-text{bottom:0;font-size:1.4em}.vjs-hidden{display:none!important}.vjs-disabled{opacity:.5;cursor:default}.video-js .vjs-offscreen{height:1px;left:-9999px;position:absolute;top:0;width:1px}.vjs-lock-showing{display:block!important;opacity:1!important;visibility:visible!important}.vjs-no-js{padding:20px;color:#fff;background-color:#000;font-size:18px;font-family:Arial,Helvetica,sans-serif;text-align:center;width:300px;height:150px;margin:0 auto}.vjs-no-js a,.vjs-no-js a:visited{color:#66a8cc}.video-js .vjs-big-play-button{font-size:3em;line-height:1.5em;height:1.63332em;width:3em;display:block;position:absolute;top:50%;left:50%;padding:0;margin-top:-.81666em;margin-left:-1.5em;cursor:pointer;opacity:1;border:.06666em solid #fff;background-color:#2b333f;background-color:rgba(43,51,63,.7);border-radius:.3em;transition:all .4s}.vjs-big-play-button .vjs-svg-icon{width:1em;height:1em;position:absolute;top:50%;left:50%;line-height:1;transform:translate(-50%,-50%)}.video-js .vjs-big-play-button:focus,.video-js:hover .vjs-big-play-button{border-color:#fff;background-color:rgb(114.9141509434,132.7028301887,159.3858490566);background-color:rgba(114.9141509434,132.7028301887,159.3858490566,.5);transition:all 0s}.vjs-controls-disabled .vjs-big-play-button,.vjs-error .vjs-big-play-button,.vjs-has-started .vjs-big-play-button,.vjs-using-native-controls .vjs-big-play-button{display:none}.vjs-has-started.vjs-paused.vjs-show-big-play-button-on-pause:not(.vjs-seeking,.vjs-scrubbing,.vjs-error) .vjs-big-play-button{display:block}.video-js button{background:0 0;border:none;color:inherit;display:inline-block;font-size:inherit;line-height:inherit;text-transform:none;text-decoration:none;transition:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.video-js.vjs-spatial-navigation-enabled .vjs-button:focus{outline:.0625em solid #fff;box-shadow:none}.vjs-control .vjs-button{width:100%;height:100%}.video-js .vjs-control.vjs-close-button{cursor:pointer;height:3em;position:absolute;right:0;top:.5em;z-index:2}.video-js .vjs-modal-dialog{background:rgba(0,0,0,.8);background:linear-gradient(180deg,rgba(0,0,0,.8),rgba(255,255,255,0));overflow:auto}.video-js .vjs-modal-dialog>*{box-sizing:border-box}.vjs-modal-dialog .vjs-modal-dialog-content{font-size:1.2em;line-height:1.5;padding:20px 24px;z-index:1}.vjs-menu-button{cursor:pointer}.vjs-menu-button.vjs-disabled{cursor:default}.vjs-workinghover .vjs-menu-button.vjs-disabled:hover .vjs-menu{display:none}.vjs-menu .vjs-menu-content{display:block;padding:0;margin:0;font-family:Arial,Helvetica,sans-serif;overflow:auto}.vjs-menu .vjs-menu-content>*{box-sizing:border-box}.vjs-scrubbing .vjs-control.vjs-menu-button:hover .vjs-menu{display:none}.vjs-menu li{display:flex;justify-content:center;list-style:none;margin:0;padding:.2em 0;line-height:1.4em;font-size:1.2em;text-align:center;text-transform:lowercase}.js-focus-visible .vjs-menu li.vjs-menu-item:hover,.vjs-menu li.vjs-menu-item:focus,.vjs-menu li.vjs-menu-item:hover{background-color:rgb(114.9141509434,132.7028301887,159.3858490566);background-color:rgba(114.9141509434,132.7028301887,159.3858490566,.5)}.js-focus-visible .vjs-menu li.vjs-selected:hover,.vjs-menu li.vjs-selected,.vjs-menu li.vjs-selected:focus,.vjs-menu li.vjs-selected:hover{background-color:#fff;color:#2b333f}.js-focus-visible .vjs-menu li.vjs-selected:hover .vjs-svg-icon,.vjs-menu li.vjs-selected .vjs-svg-icon,.vjs-menu li.vjs-selected:focus .vjs-svg-icon,.vjs-menu li.vjs-selected:hover .vjs-svg-icon{fill:#000}.js-focus-visible .vjs-menu :not(.vjs-selected):focus:not(.focus-visible),.video-js .vjs-menu :not(.vjs-selected):focus:not(:focus-visible){background:0 0}.vjs-menu li.vjs-menu-title{text-align:center;text-transform:uppercase;font-size:1em;line-height:2em;padding:0;margin:0 0 .3em 0;font-weight:700;cursor:default}.vjs-menu-button-popup .vjs-menu{display:none;position:absolute;bottom:0;width:10em;left:-3em;height:0;margin-bottom:1.5em;border-top-color:rgba(43,51,63,.7)}.vjs-pip-window .vjs-menu-button-popup .vjs-menu{left:unset;right:1em}.vjs-menu-button-popup .vjs-menu .vjs-menu-content{background-color:#2b333f;background-color:rgba(43,51,63,.7);position:absolute;width:100%;bottom:1.5em;max-height:15em}.vjs-layout-tiny .vjs-menu-button-popup .vjs-menu .vjs-menu-content,.vjs-layout-x-small .vjs-menu-button-popup .vjs-menu .vjs-menu-content{max-height:5em}.vjs-layout-small .vjs-menu-button-popup .vjs-menu .vjs-menu-content{max-height:10em}.vjs-layout-medium .vjs-menu-button-popup .vjs-menu .vjs-menu-content{max-height:14em}.vjs-layout-huge .vjs-menu-button-popup .vjs-menu .vjs-menu-content,.vjs-layout-large .vjs-menu-button-popup .vjs-menu .vjs-menu-content,.vjs-layout-x-large .vjs-menu-button-popup .vjs-menu .vjs-menu-content{max-height:25em}.vjs-menu-button-popup .vjs-menu.vjs-lock-showing,.vjs-workinghover .vjs-menu-button-popup.vjs-hover .vjs-menu{display:block}.video-js .vjs-menu-button-inline{transition:all .4s;overflow:hidden}.video-js .vjs-menu-button-inline:before{width:2.222222222em}.video-js .vjs-menu-button-inline.vjs-slider-active,.video-js .vjs-menu-button-inline:focus,.video-js .vjs-menu-button-inline:hover{width:12em}.vjs-menu-button-inline .vjs-menu{opacity:0;height:100%;width:auto;position:absolute;left:4em;top:0;padding:0;margin:0;transition:all .4s}.vjs-menu-button-inline.vjs-slider-active .vjs-menu,.vjs-menu-button-inline:focus .vjs-menu,.vjs-menu-button-inline:hover .vjs-menu{display:block;opacity:1}.vjs-menu-button-inline .vjs-menu-content{width:auto;height:100%;margin:0;overflow:hidden}.video-js .vjs-control-bar{display:none;width:100%;position:absolute;bottom:0;left:0;right:0;height:3em;background-color:#2b333f;background-color:rgba(43,51,63,.7)}.video-js.vjs-spatial-navigation-enabled .vjs-control-bar{gap:1px}.video-js:not(.vjs-controls-disabled,.vjs-using-native-controls,.vjs-error) .vjs-control-bar.vjs-lock-showing{display:flex!important}.vjs-audio-only-mode .vjs-control-bar,.vjs-has-started .vjs-control-bar{display:flex;visibility:visible;opacity:1;transition:visibility .1s,opacity .1s}.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar{visibility:visible;opacity:0;pointer-events:none;transition:visibility 1s,opacity 1s}.vjs-controls-disabled .vjs-control-bar,.vjs-error .vjs-control-bar,.vjs-using-native-controls .vjs-control-bar{display:none!important}.vjs-audio-only-mode.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar,.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar{opacity:1;visibility:visible;pointer-events:auto}.video-js .vjs-control{position:relative;text-align:center;margin:0;padding:0;height:100%;width:4em;flex:none}.video-js .vjs-control.vjs-visible-text{width:auto;padding-left:1em;padding-right:1em}.vjs-button>.vjs-icon-placeholder:before{font-size:1.8em;line-height:1.67}.vjs-button>.vjs-icon-placeholder{display:block}.vjs-button>.vjs-svg-icon{display:inline-block}.video-js .vjs-control:focus,.video-js .vjs-control:focus:before,.video-js .vjs-control:hover:before{text-shadow:0 0 1em #fff}.video-js :not(.vjs-visible-text)>.vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.video-js .vjs-custom-control-spacer{display:none}.video-js .vjs-progress-control{cursor:pointer;flex:auto;display:flex;align-items:center;min-width:4em;touch-action:none}.video-js .vjs-progress-control.disabled{cursor:default}.vjs-live .vjs-progress-control{display:none}.vjs-liveui .vjs-progress-control{display:flex;align-items:center}.video-js .vjs-progress-holder{flex:auto;transition:all .2s;height:.3em}.video-js .vjs-progress-control .vjs-progress-holder{margin:0 10px}.video-js .vjs-progress-control:hover .vjs-progress-holder,.video-js.vjs-scrubbing.vjs-touch-enabled .vjs-progress-control .vjs-progress-holder{font-size:1.6666666667em}.video-js .vjs-progress-control:hover .vjs-progress-holder.disabled{font-size:1em}.video-js .vjs-progress-holder .vjs-load-progress,.video-js .vjs-progress-holder .vjs-load-progress div,.video-js .vjs-progress-holder .vjs-play-progress{position:absolute;display:block;height:100%;margin:0;padding:0;width:0}.video-js .vjs-play-progress{background-color:#fff}.video-js .vjs-play-progress:before{font-size:.9em;position:absolute;right:-.5em;line-height:.35em;z-index:1}.vjs-svg-icons-enabled .vjs-play-progress:before{content:none!important}.vjs-play-progress .vjs-svg-icon{position:absolute;top:-.35em;right:-.4em;width:.9em;height:.9em;pointer-events:none;line-height:.15em;z-index:1}.video-js .vjs-load-progress{background:rgba(114.9141509434,132.7028301887,159.3858490566,.5)}.video-js .vjs-load-progress div{background:rgba(114.9141509434,132.7028301887,159.3858490566,.75)}.video-js .vjs-time-tooltip{background-color:#fff;background-color:rgba(255,255,255,.8);border-radius:.3em;color:#000;float:right;font-family:Arial,Helvetica,sans-serif;font-size:1em;padding:6px 8px 8px 8px;pointer-events:none;position:absolute;top:-3.4em;visibility:hidden;z-index:1}.video-js .vjs-progress-holder:focus .vjs-time-tooltip{display:none}.video-js .vjs-progress-control:hover .vjs-progress-holder:focus .vjs-time-tooltip,.video-js .vjs-progress-control:hover .vjs-time-tooltip,.video-js.vjs-scrubbing.vjs-touch-enabled .vjs-progress-control .vjs-time-tooltip{display:block;font-size:.6em;visibility:visible}.video-js .vjs-progress-control.disabled:hover .vjs-time-tooltip{font-size:1em}.video-js .vjs-progress-control .vjs-mouse-display{display:none;position:absolute;width:1px;height:100%;background-color:#000;z-index:1}.video-js .vjs-progress-control:hover .vjs-mouse-display{display:block}.video-js.vjs-scrubbing.vjs-touch-enabled .vjs-progress-control .vjs-mouse-display{display:block}.video-js.vjs-touch-enabled:not(.vjs-scrubbing) .vjs-progress-control .vjs-mouse-display,.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display{visibility:hidden;opacity:0;transition:visibility 1s,opacity 1s}.vjs-mouse-display .vjs-time-tooltip{color:#fff;background-color:#000;background-color:rgba(0,0,0,.8)}.video-js .vjs-slider{position:relative;cursor:pointer;padding:0;margin:0 .45em 0 .45em;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:rgb(114.9141509434,132.7028301887,159.3858490566);background-color:rgba(114.9141509434,132.7028301887,159.3858490566,.5)}.video-js .vjs-slider.disabled{cursor:default}.video-js .vjs-slider:focus{text-shadow:0 0 1em #fff;box-shadow:0 0 1em #fff}.video-js.vjs-spatial-navigation-enabled .vjs-slider:focus{outline:.0625em solid #fff}.video-js .vjs-mute-control{cursor:pointer;flex:none}.video-js .vjs-volume-control{cursor:pointer;margin-right:1em;display:flex}.video-js .vjs-volume-control.vjs-volume-horizontal{width:5em}.video-js .vjs-volume-panel .vjs-volume-control{visibility:visible;opacity:0;width:1px;height:1px;margin-left:-1px}.video-js .vjs-volume-panel{transition:width 1s}.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active,.video-js .vjs-volume-panel .vjs-volume-control:active,.video-js .vjs-volume-panel.vjs-hover .vjs-mute-control~.vjs-volume-control,.video-js .vjs-volume-panel.vjs-hover .vjs-volume-control,.video-js .vjs-volume-panel:active .vjs-volume-control,.video-js .vjs-volume-panel:focus .vjs-volume-control{visibility:visible;opacity:1;position:relative;transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s}.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-horizontal,.video-js .vjs-volume-panel .vjs-volume-control:active.vjs-volume-horizontal,.video-js .vjs-volume-panel.vjs-hover .vjs-mute-control~.vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel.vjs-hover .vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel:active .vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel:focus .vjs-volume-control.vjs-volume-horizontal{width:5em;height:3em;margin-right:0}.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-vertical,.video-js .vjs-volume-panel .vjs-volume-control:active.vjs-volume-vertical,.video-js .vjs-volume-panel.vjs-hover .vjs-mute-control~.vjs-volume-control.vjs-volume-vertical,.video-js .vjs-volume-panel.vjs-hover .vjs-volume-control.vjs-volume-vertical,.video-js .vjs-volume-panel:active .vjs-volume-control.vjs-volume-vertical,.video-js .vjs-volume-panel:focus .vjs-volume-control.vjs-volume-vertical{left:-3.5em;transition:left 0s}.video-js .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-hover,.video-js .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active,.video-js .vjs-volume-panel.vjs-volume-panel-horizontal:active{width:10em;transition:width .1s}.video-js .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-mute-toggle-only{width:4em}.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical{height:8em;width:3em;left:-3000em;transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s}.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal{transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s}.video-js .vjs-volume-panel{display:flex}.video-js .vjs-volume-bar{margin:1.35em .45em}.vjs-volume-bar.vjs-slider-horizontal{width:5em;height:.3em}.vjs-volume-bar.vjs-slider-vertical{width:.3em;height:5em;margin:1.35em auto}.video-js .vjs-volume-level{position:absolute;bottom:0;left:0;background-color:#fff}.video-js .vjs-volume-level:before{position:absolute;font-size:.9em;z-index:1}.vjs-slider-vertical .vjs-volume-level{width:.3em}.vjs-slider-vertical .vjs-volume-level:before{top:-.5em;left:-.3em;z-index:1}.vjs-svg-icons-enabled .vjs-volume-level:before{content:none}.vjs-volume-level .vjs-svg-icon{position:absolute;width:.9em;height:.9em;pointer-events:none;z-index:1}.vjs-slider-horizontal .vjs-volume-level{height:.3em}.vjs-slider-horizontal .vjs-volume-level:before{line-height:.35em;right:-.5em}.vjs-slider-horizontal .vjs-volume-level .vjs-svg-icon{right:-.3em;transform:translateY(-50%)}.vjs-slider-vertical .vjs-volume-level .vjs-svg-icon{top:-.55em;transform:translateX(-50%)}.video-js .vjs-volume-panel.vjs-volume-panel-vertical{width:4em}.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level{height:100%}.vjs-volume-bar.vjs-slider-horizontal .vjs-volume-level{width:100%}.video-js .vjs-volume-vertical{width:3em;height:8em;bottom:8em;background-color:#2b333f;background-color:rgba(43,51,63,.7)}.video-js .vjs-volume-horizontal .vjs-menu{left:-2em}.video-js .vjs-volume-tooltip{background-color:#fff;background-color:rgba(255,255,255,.8);border-radius:.3em;color:#000;float:right;font-family:Arial,Helvetica,sans-serif;font-size:1em;padding:6px 8px 8px 8px;pointer-events:none;position:absolute;top:-3.4em;visibility:hidden;z-index:1}.video-js .vjs-volume-control:hover .vjs-progress-holder:focus .vjs-volume-tooltip,.video-js .vjs-volume-control:hover .vjs-volume-tooltip{display:block;font-size:1em;visibility:visible}.video-js .vjs-volume-vertical:hover .vjs-progress-holder:focus .vjs-volume-tooltip,.video-js .vjs-volume-vertical:hover .vjs-volume-tooltip{left:1em;top:-12px}.video-js .vjs-volume-control.disabled:hover .vjs-volume-tooltip{font-size:1em}.video-js .vjs-volume-control .vjs-mouse-display{display:none;position:absolute;width:100%;height:1px;background-color:#000;z-index:1}.video-js .vjs-volume-horizontal .vjs-mouse-display{width:1px;height:100%}.video-js .vjs-volume-control:hover .vjs-mouse-display{display:block}.video-js.vjs-user-inactive .vjs-volume-control .vjs-mouse-display{visibility:hidden;opacity:0;transition:visibility 1s,opacity 1s}.vjs-mouse-display .vjs-volume-tooltip{color:#fff;background-color:#000;background-color:rgba(0,0,0,.8)}.vjs-poster{display:inline-block;vertical-align:middle;cursor:pointer;margin:0;padding:0;position:absolute;top:0;right:0;bottom:0;left:0;height:100%}.vjs-has-started .vjs-poster,.vjs-using-native-controls .vjs-poster{display:none}.vjs-audio.vjs-has-started .vjs-poster,.vjs-has-started.vjs-audio-poster-mode .vjs-poster,.vjs-pip-container.vjs-has-started .vjs-poster{display:block}.vjs-poster img{width:100%;height:100%;object-fit:contain}.video-js .vjs-live-control{display:flex;align-items:flex-start;flex:auto;font-size:1em;line-height:3em}.video-js.vjs-liveui .vjs-live-control,.video-js:not(.vjs-live) .vjs-live-control{display:none}.video-js .vjs-seek-to-live-control{align-items:center;cursor:pointer;flex:none;display:inline-flex;height:100%;padding-left:.5em;padding-right:.5em;font-size:1em;line-height:3em;width:auto;min-width:4em}.video-js.vjs-live:not(.vjs-liveui) .vjs-seek-to-live-control,.video-js:not(.vjs-live) .vjs-seek-to-live-control{display:none}.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge{cursor:auto}.vjs-seek-to-live-control .vjs-icon-placeholder{margin-right:.5em;color:#888}.vjs-svg-icons-enabled .vjs-seek-to-live-control{line-height:0}.vjs-seek-to-live-control .vjs-svg-icon{width:1em;height:1em;pointer-events:none;fill:#888}.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-icon-placeholder{color:red}.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-svg-icon{fill:red}.video-js .vjs-time-control{flex:none;font-size:1em;line-height:3em;min-width:2em;width:auto;padding-left:1em;padding-right:1em}.video-js .vjs-current-time,.video-js .vjs-duration,.vjs-live .vjs-time-control,.vjs-live .vjs-time-divider{display:none}.vjs-time-divider{display:none;line-height:3em}.vjs-normalise-time-controls:not(.vjs-live) .vjs-time-control{display:flex}.video-js .vjs-play-control{cursor:pointer}.video-js .vjs-play-control .vjs-icon-placeholder{flex:none}.vjs-text-track-display{position:absolute;bottom:3em;left:0;right:0;top:0;pointer-events:none}.vjs-error .vjs-text-track-display{display:none}.video-js.vjs-controls-disabled .vjs-text-track-display,.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display{bottom:1em}.video-js .vjs-text-track{font-size:1.4em;text-align:center;margin-bottom:.1em}.vjs-subtitles{color:#fff}.vjs-captions{color:#fc6}.vjs-tt-cue{display:block}video::-webkit-media-text-track-display{transform:translateY(-3em)}.video-js.vjs-controls-disabled video::-webkit-media-text-track-display,.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display{transform:translateY(-1.5em)}.video-js.vjs-force-center-align-cues .vjs-text-track-cue{text-align:center!important;width:80%!important}@supports not (inset:10px){.video-js .vjs-text-track-display>div{top:0;right:0;bottom:0;left:0}}.video-js .vjs-picture-in-picture-control{cursor:pointer;flex:none}.video-js.vjs-audio-only-mode .vjs-picture-in-picture-control,.vjs-pip-window .vjs-picture-in-picture-control{display:none}.video-js .vjs-fullscreen-control{cursor:pointer;flex:none}.video-js.vjs-audio-only-mode .vjs-fullscreen-control,.vjs-pip-window .vjs-fullscreen-control{display:none}.vjs-playback-rate .vjs-playback-rate-value,.vjs-playback-rate>.vjs-menu-button{position:absolute;top:0;left:0;width:100%;height:100%}.vjs-playback-rate .vjs-playback-rate-value{pointer-events:none;font-size:1.5em;line-height:2;text-align:center}.vjs-playback-rate .vjs-menu{width:4em;left:0}.vjs-error .vjs-error-display .vjs-modal-dialog-content{font-size:1.4em;text-align:center}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);opacity:.85;text-align:left;border:.6em solid rgba(43,51,63,.7);box-sizing:border-box;background-clip:padding-box;width:5em;height:5em;border-radius:50%;visibility:hidden}.vjs-seeking .vjs-loading-spinner,.vjs-waiting .vjs-loading-spinner{display:flex;justify-content:center;align-items:center;animation:vjs-spinner-show 0s linear .3s forwards}.vjs-error .vjs-loading-spinner{display:none}.vjs-loading-spinner:after,.vjs-loading-spinner:before{content:"";position:absolute;box-sizing:inherit;width:inherit;height:inherit;border-radius:inherit;opacity:1;border:inherit;border-color:transparent;border-top-color:#fff}.vjs-seeking .vjs-loading-spinner:after,.vjs-seeking .vjs-loading-spinner:before,.vjs-waiting .vjs-loading-spinner:after,.vjs-waiting .vjs-loading-spinner:before{animation:vjs-spinner-spin 1.1s cubic-bezier(.6,.2,0,.8) infinite,vjs-spinner-fade 1.1s linear infinite}.vjs-seeking .vjs-loading-spinner:before,.vjs-waiting .vjs-loading-spinner:before{border-top-color:#fff}.vjs-seeking .vjs-loading-spinner:after,.vjs-waiting .vjs-loading-spinner:after{border-top-color:#fff;animation-delay:.44s}@keyframes vjs-spinner-show{to{visibility:visible}}@keyframes vjs-spinner-spin{100%{transform:rotate(360deg)}}@keyframes vjs-spinner-fade{0%{border-top-color:rgb(114.9141509434,132.7028301887,159.3858490566)}20%{border-top-color:rgb(114.9141509434,132.7028301887,159.3858490566)}35%{border-top-color:#fff}60%{border-top-color:rgb(114.9141509434,132.7028301887,159.3858490566)}100%{border-top-color:rgb(114.9141509434,132.7028301887,159.3858490566)}}.video-js.vjs-audio-only-mode .vjs-captions-button{display:none}.vjs-chapters-button .vjs-menu ul{width:24em}.video-js.vjs-audio-only-mode .vjs-descriptions-button{display:none}.vjs-subs-caps-button+.vjs-menu .vjs-captions-menu-item .vjs-svg-icon{width:1.5em;height:1.5em}.video-js .vjs-subs-caps-button+.vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder{vertical-align:middle;display:inline-block;margin-bottom:-.1em}.video-js .vjs-subs-caps-button+.vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before{font-family:VideoJS;content:"\f10c";font-size:1.5em;line-height:inherit}.video-js.vjs-audio-only-mode .vjs-subs-caps-button{display:none}.video-js .vjs-audio-button+.vjs-menu .vjs-descriptions-menu-item .vjs-menu-item-text .vjs-icon-placeholder,.video-js .vjs-audio-button+.vjs-menu .vjs-main-desc-menu-item .vjs-menu-item-text .vjs-icon-placeholder{vertical-align:middle;display:inline-block;margin-bottom:-.1em}.video-js .vjs-audio-button+.vjs-menu .vjs-descriptions-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before,.video-js .vjs-audio-button+.vjs-menu .vjs-main-desc-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before{font-family:VideoJS;content:" \f12e";font-size:1.5em;line-height:inherit}.video-js.vjs-layout-small .vjs-current-time,.video-js.vjs-layout-small .vjs-duration,.video-js.vjs-layout-small .vjs-playback-rate,.video-js.vjs-layout-small .vjs-remaining-time,.video-js.vjs-layout-small .vjs-time-divider,.video-js.vjs-layout-small .vjs-volume-control,.video-js.vjs-layout-tiny .vjs-current-time,.video-js.vjs-layout-tiny .vjs-duration,.video-js.vjs-layout-tiny .vjs-playback-rate,.video-js.vjs-layout-tiny .vjs-remaining-time,.video-js.vjs-layout-tiny .vjs-time-divider,.video-js.vjs-layout-tiny .vjs-volume-control,.video-js.vjs-layout-x-small .vjs-current-time,.video-js.vjs-layout-x-small .vjs-duration,.video-js.vjs-layout-x-small .vjs-playback-rate,.video-js.vjs-layout-x-small .vjs-remaining-time,.video-js.vjs-layout-x-small .vjs-time-divider,.video-js.vjs-layout-x-small .vjs-volume-control{display:none}.video-js.vjs-layout-small .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-hover,.video-js.vjs-layout-small .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active,.video-js.vjs-layout-small .vjs-volume-panel.vjs-volume-panel-horizontal:active,.video-js.vjs-layout-small .vjs-volume-panel.vjs-volume-panel-horizontal:hover,.video-js.vjs-layout-tiny .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-hover,.video-js.vjs-layout-tiny .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active,.video-js.vjs-layout-tiny .vjs-volume-panel.vjs-volume-panel-horizontal:active,.video-js.vjs-layout-tiny .vjs-volume-panel.vjs-volume-panel-horizontal:hover,.video-js.vjs-layout-x-small .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-hover,.video-js.vjs-layout-x-small .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active,.video-js.vjs-layout-x-small .vjs-volume-panel.vjs-volume-panel-horizontal:active,.video-js.vjs-layout-x-small .vjs-volume-panel.vjs-volume-panel-horizontal:hover{width:auto;width:initial}.video-js.vjs-layout-tiny .vjs-progress-control,.video-js.vjs-layout-x-small .vjs-progress-control{display:none}.video-js.vjs-layout-x-small .vjs-custom-control-spacer{flex:auto;display:block}.vjs-modal-dialog.vjs-text-track-settings{background-color:#2b333f;background-color:rgba(43,51,63,.75);color:#fff;height:70%}.vjs-spatial-navigation-enabled .vjs-modal-dialog.vjs-text-track-settings{height:80%}.vjs-error .vjs-text-track-settings{display:none}.vjs-text-track-settings .vjs-modal-dialog-content{display:table}.vjs-text-track-settings .vjs-track-settings-colors,.vjs-text-track-settings .vjs-track-settings-controls,.vjs-text-track-settings .vjs-track-settings-font{display:table-cell}.vjs-text-track-settings .vjs-track-settings-controls{text-align:right;vertical-align:bottom}@supports (display:grid){.vjs-text-track-settings .vjs-modal-dialog-content{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr;padding:20px 24px 0 24px}.vjs-track-settings-controls .vjs-default-button{margin-bottom:20px}.vjs-text-track-settings .vjs-track-settings-controls{grid-column:1/-1}.vjs-layout-small .vjs-text-track-settings .vjs-modal-dialog-content,.vjs-layout-tiny .vjs-text-track-settings .vjs-modal-dialog-content,.vjs-layout-x-small .vjs-text-track-settings .vjs-modal-dialog-content{grid-template-columns:1fr}}.vjs-text-track-settings select{font-size:inherit}.vjs-track-setting>select{margin-right:1em;margin-bottom:.5em}.vjs-text-track-settings fieldset{margin:10px;border:none}.vjs-text-track-settings fieldset span{display:inline-block;padding:0 .6em .8em}.vjs-text-track-settings fieldset span>select{max-width:7.3em}.vjs-text-track-settings legend{color:#fff;font-weight:700;font-size:1.2em}.vjs-text-track-settings .vjs-label{margin:0 .5em .5em 0}.vjs-track-settings-controls button:active,.vjs-track-settings-controls button:focus{outline-style:solid;outline-width:medium;background-image:linear-gradient(0deg,#fff 88%,rgb(114.9141509434,132.7028301887,159.3858490566) 100%)}.vjs-track-settings-controls button:hover{color:rgba(43,51,63,.75)}.vjs-track-settings-controls button{background-color:#fff;background-image:linear-gradient(-180deg,#fff 88%,rgb(114.9141509434,132.7028301887,159.3858490566) 100%);color:#2b333f;cursor:pointer;border-radius:2px}.vjs-track-settings-controls .vjs-default-button{margin-right:1em}.vjs-title-bar{background:rgba(0,0,0,.9);background:linear-gradient(180deg,rgba(0,0,0,.9) 0,rgba(0,0,0,.7) 60%,rgba(0,0,0,0) 100%);font-size:1.2em;line-height:1.5;transition:opacity .1s;padding:.666em 1.333em 4em;pointer-events:none;position:absolute;top:0;width:100%}.vjs-error .vjs-title-bar{display:none}.vjs-title-bar-description,.vjs-title-bar-title{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vjs-title-bar-title{font-weight:700;margin-bottom:.333em}.vjs-playing.vjs-user-inactive .vjs-title-bar{opacity:0;transition:opacity 1s}.video-js .vjs-skip-forward-5{cursor:pointer}.video-js .vjs-skip-forward-10{cursor:pointer}.video-js .vjs-skip-forward-30{cursor:pointer}.video-js .vjs-skip-backward-5{cursor:pointer}.video-js .vjs-skip-backward-10{cursor:pointer}.video-js .vjs-skip-backward-30{cursor:pointer}.video-js .vjs-transient-button{position:absolute;height:3em;display:flex;align-items:center;justify-content:center;background-color:rgba(50,50,50,.5);cursor:pointer;opacity:1;transition:opacity 1s}.video-js:not(.vjs-has-started) .vjs-transient-button{display:none}.video-js.not-hover .vjs-transient-button:not(.force-display),.video-js.vjs-user-inactive .vjs-transient-button:not(.force-display){opacity:0}.video-js .vjs-transient-button span{padding:0 .5em}.video-js .vjs-transient-button.vjs-left{left:1em}.video-js .vjs-transient-button.vjs-right{right:1em}.video-js .vjs-transient-button.vjs-top{top:1em}.video-js .vjs-transient-button.vjs-near-top{top:4em}.video-js .vjs-transient-button.vjs-bottom{bottom:4em}.video-js .vjs-transient-button:hover{background-color:rgba(50,50,50,.9)}@media print{.video-js>:not(.vjs-tech):not(.vjs-poster){visibility:hidden}}.vjs-resize-manager{position:absolute;top:0;left:0;width:100%;height:100%;border:none;z-index:-1000}.js-focus-visible .video-js :focus:not(.focus-visible){outline:0}.video-js :focus:not(:focus-visible){outline:0} \ No newline at end of file diff --git a/view/js/videojs/video.min.js b/view/js/videojs/video.min.js new file mode 100644 index 0000000000..06474a27a1 --- /dev/null +++ b/view/js/videojs/video.min.js @@ -0,0 +1,53 @@ +/** + * @license + * Video.js 8.23.4 + * Copyright Brightcove, Inc. + * Available under Apache License Version 2.0 + * + * + * Includes vtt.js + * Available under Apache License Version 2.0 + * + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).videojs=t()}(this,function(){var M="8.23.4";let U={},B=function(e,t){return U[e]=U[e]||[],t&&(U[e]=U[e].concat(t)),U[e]};function F(e,t){return!((t=B(e).indexOf(t))<=-1||(U[e]=U[e].slice(),U[e].splice(t,1),0))}let q={prefixed:!0};var j=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror","fullscreen"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror","-webkit-full-screen"]],V=j[0];let H;for(let e=0;e{var e,i=d.levels[i],r=new RegExp(`^(${i})$`);let n=l;if("log"!==t&&s.unshift(t.toUpperCase()+":"),h&&(n="%c"+l,s.unshift(h)),s.unshift(n+":"),z&&(z.push([].concat(s)),e=z.length-1e3,z.splice(0,0s(r+` ${t=void 0!==t?t:n} `+e,t,void 0!==i?i:a),o.createNewLogger=(e,t,i)=>s(e,t,i),o.levels={all:"debug|log|warn|error",off:"",debug:"debug|log|warn|error",info:"log|warn|error",warn:"warn|error",error:"error",DEFAULT:t},o.level=e=>{if("string"==typeof e){if(!o.levels.hasOwnProperty(e))throw new Error(`"${e}" in not a valid log level`);t=e}return t},(o.history=()=>z?[].concat(z):[]).filter=t=>(z||[]).filter(e=>new RegExp(`.*${t}.*`).test(e[0])),o.history.clear=()=>{z&&(z.length=0)},o.history.disable=()=>{null!==z&&(z.length=0,z=null)},o.history.enable=()=>{null===z&&(z=[])},o.error=(...e)=>i("error",t,e),o.warn=(...e)=>i("warn",t,e),o.debug=(...e)=>i("debug",t,e),o}("VIDEOJS"),W=o.createLogger,G=Object.prototype.toString;function X(t,i){$(t).forEach(e=>i(t[e],e))}function K(i,s,e=0){return $(i).reduce((e,t)=>s(e,i[t],t),e)}function Y(e){return!!e&&"object"==typeof e}function Q(e){return Y(e)&&"[object Object]"===G.call(e)&&e.constructor===Object}function d(...e){let i={};return e.forEach(e=>{e&&X(e,(e,t)=>{Q(e)?(Q(i[t])||(i[t]={}),i[t]=d(i[t],e)):i[t]=e})}),i}function J(e={}){var t,i,s=[];for(t in e)e.hasOwnProperty(t)&&(i=e[t],s.push(i));return s}function Z(t,i,s,e=!0){let r=e=>Object.defineProperty(t,i,{value:e,enumerable:!0,writable:!0});var n={configurable:!0,enumerable:!0,get(){var e=s();return r(e),e}};return e&&(n.set=r),Object.defineProperty(t,i,n)}let ee=Object.freeze({__proto__:null,each:X,reduce:K,isObject:Y,isPlain:Q,merge:d,values:J,defineLazyProperty:Z}),te=!1,ie=null,se=!1,re,ne=!1,ae=!1,oe=!1,le=!1,de=null,he=null;var e=Boolean(window.cast&&window.cast.framework&&window.cast.framework.CastReceiverContext);let ue=null,ce=!1,pe=!1,me=!1,ge=!1,fe=!1,ye=!1,_e=!1,ve=Boolean(Ee()&&("ontouchstart"in window||window.navigator.maxTouchPoints||window.DocumentTouch&&window.document instanceof window.DocumentTouch));var be,t=window.navigator&&window.navigator.userAgentData;if(t&&t.platform&&t.brands&&(se="Android"===t.platform,ae=Boolean(t.brands.find(e=>"Microsoft Edge"===e.brand)),oe=Boolean(t.brands.find(e=>"Chromium"===e.brand)),le=!ae&&oe,de=he=(t.brands.find(e=>"Chromium"===e.brand)||{}).version||null,pe="Windows"===t.platform),!oe){let i=window.navigator&&window.navigator.userAgent||"";te=/iPod/i.test(i),ie=(t=i.match(/OS (\d+)_/i))&&t[1]?t[1]:null,se=/Android/i.test(i),re=(t=i.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i))?(bi=t[1]&&parseFloat(t[1]),be=t[2]&&parseFloat(t[2]),bi&&be?parseFloat(t[1]+"."+t[2]):bi||null):null,ne=/Firefox/i.test(i),ae=/Edg/i.test(i),oe=/Chrome/i.test(i)||/CriOS/i.test(i),le=!ae&&oe,de=he=(be=i.match(/(Chrome|CriOS)\/(\d+)/))&&be[2]?parseFloat(be[2]):null,ue=function(){var e=/MSIE\s(\d+)\.\d/.exec(i);let t=e&&parseFloat(e[1]);return t=!t&&/Trident\/7.0/i.test(i)&&/rv:11.0/.test(i)?11:t}(),fe=/Tizen/i.test(i),ye=/Web0S/i.test(i),_e=fe||ye,ce=/Safari/i.test(i)&&!le&&!se&&!ae&&!_e,pe=/Windows/i.test(i),me=/iPad/i.test(i)||ce&&ve&&!/iPhone/i.test(i),ge=/iPhone/i.test(i)&&!me}let u=ge||me||te,Te=(ce||u)&&!le;var Se=Object.freeze({__proto__:null,get IS_IPOD(){return te},get IOS_VERSION(){return ie},get IS_ANDROID(){return se},get ANDROID_VERSION(){return re},get IS_FIREFOX(){return ne},get IS_EDGE(){return ae},get IS_CHROMIUM(){return oe},get IS_CHROME(){return le},get CHROMIUM_VERSION(){return de},get CHROME_VERSION(){return he},IS_CHROMECAST_RECEIVER:e,get IE_VERSION(){return ue},get IS_SAFARI(){return ce},get IS_WINDOWS(){return pe},get IS_IPAD(){return me},get IS_IPHONE(){return ge},get IS_TIZEN(){return fe},get IS_WEBOS(){return ye},get IS_SMART_TV(){return _e},TOUCH_ENABLED:ve,IS_IOS:u,IS_ANY_SAFARI:Te});function we(e){return"string"==typeof e&&Boolean(e.trim())}function Ee(){return document===window.document}function Ce(e){return Y(e)&&1===e.nodeType}function ke(){try{return window.parent!==window.self}catch(e){return!0}}function Ie(i){return function(e,t){return we(e)?(t=Ce(t=we(t)?document.querySelector(t):t)?t:document)[i]&&t[i](e):document[i](null)}}function l(e="div",i={},t={},s){let r=document.createElement(e);return Object.getOwnPropertyNames(i).forEach(function(e){var t=i[e];"textContent"===e?xe(r,t):r[e]===t&&"tabIndex"!==e||(r[e]=t)}),Object.getOwnPropertyNames(t).forEach(function(e){r.setAttribute(e,t[e])}),s&&Ge(r,s),r}function xe(e,t){return"undefined"==typeof e.textContent?e.innerText=t:e.textContent=t,e}function Ae(e,t){t.firstChild?t.insertBefore(e,t.firstChild):t.appendChild(e)}function De(e,t){if(0<=t.indexOf(" "))throw new Error("class has illegal whitespace characters");return e.classList.contains(t)}function Pe(e,...t){return e.classList.add(...t.reduce((e,t)=>e.concat(t.split(/\s+/)),[])),e}function Le(e,...t){return e?(e.classList.remove(...t.reduce((e,t)=>e.concat(t.split(/\s+/)),[])),e):(o.warn("removeClass was called with an element that doesn't exist"),null)}function Oe(t,e,i){return"boolean"!=typeof(i="function"==typeof i?i(t,e):i)&&(i=void 0),e.split(/\s+/).forEach(e=>t.classList.toggle(e,i)),t}function Re(i,s){Object.getOwnPropertyNames(s).forEach(function(e){var t=s[e];null===t||"undefined"==typeof t||!1===t?i.removeAttribute(e):i.setAttribute(e,!0===t?"":t)})}function Ne(e){var i={},s=["autoplay","controls","playsinline","loop","muted","default","defaultMuted"];if(e&&e.attributes&&0{void 0!==t[e]&&(i[e]=t[e])}),i.height||(i.height=parseFloat(Je(e,"height"))),i.width||(i.width=parseFloat(Je(e,"width"))),i}}function Ve(e){if(!e||!e.offsetParent)return{left:0,top:0,width:0,height:0};var t=e.offsetWidth,i=e.offsetHeight;let s=0,r=0;for(;e.offsetParent&&e!==document[q.fullscreenElement];)s+=e.offsetLeft,r+=e.offsetTop,e=e.offsetParent;return{left:s,top:r,width:t,height:i}}function He(t,e){var i={x:0,y:0};if(u){let e=t;for(;e&&"html"!==e.nodeName.toLowerCase();){var s,r=Je(e,"transform");/^matrix/.test(r)?(s=r.slice(7,-1).split(/,\s/).map(Number),i.x+=s[4],i.y+=s[5]):/^matrix3d/.test(r)&&(s=r.slice(9,-1).split(/,\s/).map(Number),i.x+=s[12],i.y+=s[13]),e.assignedSlot&&e.assignedSlot.parentElement&&window.WebKitCSSMatrix&&(r=window.getComputedStyle(e.assignedSlot.parentElement).transform,r=new window.WebKitCSSMatrix(r),i.x+=r.m41,i.y+=r.m42),e=e.parentNode||e.host}}var n={},a=Ve(e.target),t=Ve(t),o=t.width,l=t.height;let d=e.offsetY-(t.top-a.top),h=e.offsetX-(t.left-a.left);return e.changedTouches&&(h=e.changedTouches[0].pageX-t.left,d=e.changedTouches[0].pageY+t.top,u)&&(h-=i.x,d-=i.y),n.y=1-Math.max(0,Math.min(1,d/l)),n.x=Math.max(0,Math.min(1,h/o)),n}function ze(e){return Y(e)&&3===e.nodeType}function $e(e){for(;e.firstChild;)e.removeChild(e.firstChild);return e}function We(e){return"function"==typeof e&&(e=e()),(Array.isArray(e)?e:[e]).map(e=>Ce(e="function"==typeof e?e():e)||ze(e)?e:"string"==typeof e&&/\S/.test(e)?document.createTextNode(e):void 0).filter(e=>e)}function Ge(t,e){return We(e).forEach(e=>t.appendChild(e)),t}function Xe(e,t){return Ge($e(e),t)}function Ke(e){return void 0===e.button&&void 0===e.buttons||0===e.button&&void 0===e.buttons||"mouseup"===e.type&&0===e.button&&0===e.buttons||"mousedown"===e.type&&0===e.button&&0===e.buttons||0===e.button&&1===e.buttons}let Ye=Ie("querySelector"),Qe=Ie("querySelectorAll");function Je(t,i){if(!t||!i)return"";if("function"!=typeof window.getComputedStyle)return"";{let e;try{e=window.getComputedStyle(t)}catch(e){return""}return e?e.getPropertyValue(i)||e[i]:""}}function Ze(s){[...document.styleSheets].forEach(t=>{try{var i=[...t.cssRules].map(e=>e.cssText).join(""),e=document.createElement("style");e.textContent=i,s.document.head.appendChild(e)}catch(e){i=document.createElement("link");i.rel="stylesheet",i.type=t.type,i.media=t.media.mediaText,i.href=t.href,s.document.head.appendChild(i)}})}var et=Object.freeze({__proto__:null,isReal:Ee,isEl:Ce,isInFrame:ke,createEl:l,textContent:xe,prependTo:Ae,hasClass:De,addClass:Pe,removeClass:Le,toggleClass:Oe,setAttributes:Re,getAttributes:Ne,getAttribute:Me,setAttribute:Ue,removeAttribute:Be,blockTextSelection:Fe,unblockTextSelection:qe,getBoundingClientRect:je,findPosition:Ve,getPointerPosition:He,isTextNode:ze,emptyEl:$e,normalizeContent:We,appendContent:Ge,insertContent:Xe,isSingleLeftClick:Ke,$:Ye,$$:Qe,computedStyle:Je,copyStyleSheetsToWindow:Ze});function tt(){if(!1!==st.options.autoSetup){var e=Array.prototype.slice.call(document.getElementsByTagName("video")),t=Array.prototype.slice.call(document.getElementsByTagName("audio")),i=Array.prototype.slice.call(document.getElementsByTagName("video-js")),s=e.concat(t,i);if(s&&0=s&&(i(...e),r=t)}}function bt(s,r,n,a=window){let o;function e(){let e=this,t=arguments,i=function(){o=null,i=null,n||s.apply(e,t)};!o&&n&&s.apply(e,t),a.clearTimeout(o),o=a.setTimeout(i,r)}return e.cancel=()=>{a.clearTimeout(o),o=null},e}let Tt=Object.freeze({__proto__:null,UPDATE_REFRESH_INTERVAL:30,bind_:p,throttle:vt,debounce:bt}),St;class wt{on(e,t){var i=this.addEventListener;this.addEventListener=()=>{},mt(this,e,t),this.addEventListener=i}off(e,t){c(this,e,t)}one(e,t){var i=this.addEventListener;this.addEventListener=()=>{},ft(this,e,t),this.addEventListener=i}any(e,t){var i=this.addEventListener;this.addEventListener=()=>{},yt(this,e,t),this.addEventListener=i}trigger(e){var t=e.type||e;e=ut(e="string"==typeof e?{type:t}:e),this.allowedEvents_[t]&&this["on"+t]&&this["on"+t](e),gt(this,e)}queueTrigger(e){St=St||new Map;let t=e.type||e,i=St.get(this);i||(i=new Map,St.set(this,i));var s=i.get(t),s=(i.delete(t),window.clearTimeout(s),window.setTimeout(()=>{i.delete(t),0===i.size&&(i=null,St.delete(this)),this.trigger(e)},0));i.set(t,s)}}wt.prototype.allowedEvents_={},wt.prototype.addEventListener=wt.prototype.on,wt.prototype.removeEventListener=wt.prototype.off,wt.prototype.dispatchEvent=wt.prototype.trigger;let Et=e=>"function"==typeof e.name?e.name():"string"==typeof e.name?e.name:e.name_||(e.constructor&&e.constructor.name?e.constructor.name:typeof e),Ct=t=>t instanceof wt||!!t.eventBusEl_&&["on","one","off","trigger"].every(e=>"function"==typeof t[e]),kt=e=>"string"==typeof e&&/\S/.test(e)||Array.isArray(e)&&!!e.length,It=(e,t,i)=>{if(!e||!e.nodeName&&!Ct(e))throw new Error(`Invalid target for ${Et(t)}#${i}; must be a DOM node or evented object.`)},xt=(e,t,i)=>{if(!kt(e))throw new Error(`Invalid event type for ${Et(t)}#${i}; must be a non-empty string or array.`)},At=(e,t,i)=>{if("function"!=typeof e)throw new Error(`Invalid listener for ${Et(t)}#${i}; must be a function.`)},Dt=(e,t,i)=>{var s=t.length<3||t[0]===e||t[0]===e.eventBusEl_;let r,n,a;return s?(r=e.eventBusEl_,3<=t.length&&t.shift(),[n,a]=t):(r=t[0],n=t[1],a=t[2]),It(r,e,i),xt(n,e,i),At(a,e,i),a=p(e,a),{isTargetingSelf:s,target:r,type:n,listener:a}},Pt=(e,t,i,s)=>{It(e,e,t),e.nodeName?_t[t](e,i,s):e[t](i,s)},Lt={on(...t){let{isTargetingSelf:e,target:i,type:s,listener:r}=Dt(this,t,"on");if(Pt(i,"on",s,r),!e){let e=()=>this.off(i,s,r);e.guid=r.guid;t=()=>this.off("dispose",e);t.guid=r.guid,Pt(this,"on","dispose",e),Pt(i,"on","dispose",t)}},one(...e){let{isTargetingSelf:t,target:i,type:s,listener:r}=Dt(this,e,"one");if(t)Pt(i,"one",s,r);else{let t=(...e)=>{this.off(i,s,t),r.apply(null,e)};t.guid=r.guid,Pt(i,"one",s,t)}},any(...e){let{isTargetingSelf:t,target:i,type:s,listener:r}=Dt(this,e,"any");if(t)Pt(i,"any",s,r);else{let t=(...e)=>{this.off(i,s,t),r.apply(null,e)};t.guid=r.guid,Pt(i,"any",s,t)}},off(e,t,i){!e||kt(e)?c(this.eventBusEl_,e,t):(e=e,t=t,It(e,this,"off"),xt(t,this,"off"),At(i,this,"off"),i=p(this,i),this.off("dispose",i),e.nodeName?(c(e,t,i),c(e,"dispose",i)):Ct(e)&&(e.off(t,i),e.off("dispose",i)))},trigger(e,t){It(this.eventBusEl_,this,"trigger");var i=e&&"string"!=typeof e?e.type:e;if(kt(i))return gt(this.eventBusEl_,e,t);throw new Error(`Invalid event type for ${Et(this)}#trigger; `+"must be a non-empty string or object with a type key that has a non-empty value.")}};function Ot(e,t={}){t=t.eventBusKey;if(t){if(!e[t].nodeName)throw new Error(`The eventBusKey "${t}" does not refer to an element.`);e.eventBusEl_=e[t]}else e.eventBusEl_=l("span",{className:"vjs-event-bus"});Object.assign(e,Lt),e.eventedCallbacks&&e.eventedCallbacks.forEach(e=>{e()}),e.on("dispose",()=>{e.off(),[e,e.el_,e.eventBusEl_].forEach(function(e){e&&h.has(e)&&h.delete(e)}),window.setTimeout(()=>{e.eventBusEl_=null},0)})}let Rt={state:{},setState(e){"function"==typeof e&&(e=e());let i;return X(e,(e,t)=>{this.state[t]!==e&&((i=i||{})[t]={from:this.state[t],to:e}),this.state[t]=e}),i&&Ct(this)&&this.trigger({changes:i,type:"statechanged"}),i}};function Nt(e,t){Object.assign(e,Rt),e.state=Object.assign({},e.state,t),"function"==typeof e.handleStateChanged&&Ct(e)&&e.on("statechanged",e.handleStateChanged)}function Mt(e){return"string"!=typeof e?e:e.replace(/./,e=>e.toLowerCase())}function m(e){return"string"!=typeof e?e:e.replace(/./,e=>e.toUpperCase())}function Ut(e,t){return m(e)===m(t)}let Bt=Object.freeze({__proto__:null,toLowerCase:Mt,toTitleCase:m,titleCaseEquals:Ut});class g{constructor(e,t,i){!e&&this.play?this.player_=e=this:this.player_=e,this.isDisposed_=!1,this.parentComponent_=null,this.options_=d({},this.options_),t=this.options_=d(this.options_,t),this.id_=t.id||t.el&&t.el.id,this.id_||(e=e&&e.id&&e.id()||"no_player",this.id_=e+"_component_"+lt++),this.name_=t.name||null,t.el?this.el_=t.el:!1!==t.createEl&&(this.el_=this.createEl()),t.className&&this.el_&&t.className.split(" ").forEach(e=>this.addClass(e)),["on","off","one","any","trigger"].forEach(e=>{this[e]=void 0}),!1!==t.evented&&(Ot(this,{eventBusKey:this.el_?"el_":null}),this.handleLanguagechange=this.handleLanguagechange.bind(this),this.on(this.player_,"languagechange",this.handleLanguagechange)),Nt(this,this.constructor.defaultState),this.children_=[],this.childIndex_={},this.childNameIndex_={},this.setTimeoutIds_=new Set,this.setIntervalIds_=new Set,this.rafIds_=new Set,this.namedRafs_=new Map,(this.clearingTimersOnDispose_=!1)!==t.initChildren&&this.initChildren(),this.ready(i),!1!==t.reportTouchActivity&&this.enableTouchActivity()}dispose(e={}){if(!this.isDisposed_){if(this.readyQueue_&&(this.readyQueue_.length=0),this.trigger({type:"dispose",bubbles:!1}),this.isDisposed_=!0,this.children_)for(let e=this.children_.length-1;0<=e;e--)this.children_[e].dispose&&this.children_[e].dispose();this.children_=null,this.childIndex_=null,this.childNameIndex_=null,this.parentComponent_=null,this.el_&&(this.el_.parentNode&&(e.restoreEl?this.el_.parentNode.replaceChild(e.restoreEl,this.el_):this.el_.parentNode.removeChild(this.el_)),this.el_=null),this.player_=null}}isDisposed(){return Boolean(this.isDisposed_)}player(){return this.player_}options(e){return e&&(this.options_=d(this.options_,e)),this.options_}el(){return this.el_}createEl(e,t,i){return l(e,t,i)}localize(e,s,t=e){var i=this.player_.language&&this.player_.language(),r=this.player_.languages&&this.player_.languages(),n=r&&r[i],i=i&&i.split("-")[0],r=r&&r[i];let a=t;return n&&n[e]?a=n[e]:r&&r[e]&&(a=r[e]),a=s?a.replace(/\{(\d+)\}/g,function(e,t){t=s[t-1];let i="undefined"==typeof t?e:t;return i}):a}handleLanguagechange(){}contentEl(){return this.contentEl_||this.el_}id(){return this.id_}name(){return this.name_}children(){return this.children_}getChildById(e){return this.childIndex_[e]}getChild(e){if(e)return this.childNameIndex_[e]}getDescendant(...t){t=t.reduce((e,t)=>e.concat(t),[]);let i=this;for(let e=0;e{let t,i;return i="string"==typeof e?(t=e,r[t]||this.options_[t]||{}):(t=e.name,e),{name:t,opts:i}}).filter(e=>{e=g.getComponent(e.opts.componentClass||m(e.name));return e&&!t.isTech(e)}).forEach(e=>{var t=e.name;let i=e.opts;!1!==(i=void 0!==s[t]?s[t]:i)&&((i=!0===i?{}:i).playerOptions=this.options_.playerOptions,e=this.addChild(t,i))&&(this[t]=e)})}}buildCSSClass(){return""}ready(e,t=!1){e&&(this.isReady_?t?e.call(this):this.setTimeout(e,1):(this.readyQueue_=this.readyQueue_||[],this.readyQueue_.push(e)))}triggerReady(){this.isReady_=!0,this.setTimeout(function(){var e=this.readyQueue_;this.readyQueue_=[],e&&0{this.setTimeoutIds_.has(i)&&this.setTimeoutIds_.delete(i),e()},t),this.setTimeoutIds_.add(i),i}clearTimeout(e){return this.setTimeoutIds_.has(e)&&(this.setTimeoutIds_.delete(e),window.clearTimeout(e)),e}setInterval(e,t){e=p(this,e),this.clearTimersOnDispose_();e=window.setInterval(e,t);return this.setIntervalIds_.add(e),e}clearInterval(e){return this.setIntervalIds_.has(e)&&(this.setIntervalIds_.delete(e),window.clearInterval(e)),e}requestAnimationFrame(e){var t;return this.clearTimersOnDispose_(),e=p(this,e),t=window.requestAnimationFrame(()=>{this.rafIds_.has(t)&&this.rafIds_.delete(t),e()}),this.rafIds_.add(t),t}requestNamedAnimationFrame(e,t){this.namedRafs_.has(e)&&this.cancelNamedAnimationFrame(e),this.clearTimersOnDispose_(),t=p(this,t);var i=this.requestAnimationFrame(()=>{t(),this.namedRafs_.has(e)&&this.namedRafs_.delete(e)});return this.namedRafs_.set(e,i),e}cancelNamedAnimationFrame(e){this.namedRafs_.has(e)&&(this.cancelAnimationFrame(this.namedRafs_.get(e)),this.namedRafs_.delete(e))}cancelAnimationFrame(e){return this.rafIds_.has(e)&&(this.rafIds_.delete(e),window.cancelAnimationFrame(e)),e}clearTimersOnDispose_(){this.clearingTimersOnDispose_||(this.clearingTimersOnDispose_=!0,this.one("dispose",()=>{[["namedRafs_","cancelNamedAnimationFrame"],["rafIds_","cancelAnimationFrame"],["setTimeoutIds_","clearTimeout"],["setIntervalIds_","clearInterval"]].forEach(([e,i])=>{this[e].forEach((e,t)=>this[i](t))}),this.clearingTimersOnDispose_=!1}))}getIsDisabled(){return Boolean(this.el_.disabled)}getIsExpresslyInert(){return this.el_.inert&&!this.el_.ownerDocument.documentElement.inert}getIsFocusable(e){return 0<=(e||this.el_).tabIndex&&!(this.getIsDisabled()||this.getIsExpresslyInert())}getIsAvailableToBeFocused(e){function t(e){var e=window.getComputedStyle(e,null),t=e.getPropertyValue("visibility");return"none"!==e.getPropertyValue("display")&&!["hidden","collapse"].includes(t)}var i;return!(!function(t){if(t.offsetWidth+t.offsetHeight+t.getBoundingClientRect().height+t.getBoundingClientRect().width!==0){var i={x:t.getBoundingClientRect().left+t.offsetWidth/2,y:t.getBoundingClientRect().top+t.offsetHeight/2};if(!(i.x<0||i.x>(document.documentElement.clientWidth||window.innerWidth)||i.y<0||i.y>(document.documentElement.clientHeight||window.innerHeight))){let e=document.elementFromPoint(i.x,i.y);for(;e;){if(e===t)return 1;if(!e.parentNode)return;e=e.parentNode}}}}(e=e||this.el())||!t((i=e).parentElement)||!t(i)||"0"===i.style.opacity||"0px"===window.getComputedStyle(i).height||"0px"===window.getComputedStyle(i).width||e.parentElement&&!(0<=e.tabIndex))}static registerComponent(t,e){if("string"!=typeof t||!t)throw new Error(`Illegal component name, "${t}"; must be a non-empty string.`);var i=g.getComponent("Tech"),i=i&&i.isTech(e),s=g===e||g.prototype.isPrototypeOf(e.prototype);if(i||!s){let e;throw e=i?"techs must be registered using Tech.registerTech()":"must be a Component subclass",new Error(`Illegal component, "${t}"; ${e}.`)}t=m(t),g.components_||(g.components_={});s=g.getComponent("Player");if("Player"===t&&s&&s.players){var r=s.players,n=Object.keys(r);if(r&&0(e||[]).values()),t}function jt(e,t){return Array.isArray(e)?qt(e):void 0===e||void 0===t?qt():qt([[e,t]])}g.registerComponent("Component",g);function Vt(e,t){e=e<0?0:e;let i=Math.floor(e%60),s=Math.floor(e/60%60),r=Math.floor(e/3600);var n=Math.floor(t/60%60),t=Math.floor(t/3600);return r=0<(r=!isNaN(e)&&e!==1/0?r:s=i="-")||0i&&(n=i),s+=n-r;return s/i}function i(e){if(e instanceof i)return e;"number"==typeof e?this.code=e:"string"==typeof e?this.message=e:Y(e)&&("number"==typeof e.code&&(this.code=e.code),Object.assign(this,e)),this.message||(this.message=i.defaultMessages[this.code]||"")}function Xt(e){return null!=e&&"function"==typeof e.then}function Kt(e){Xt(e)&&e.then(null,e=>{})}i.prototype.code=0,i.prototype.message="",i.prototype.status=null,i.prototype.metadata=null,i.errorTypes=["MEDIA_ERR_CUSTOM","MEDIA_ERR_ABORTED","MEDIA_ERR_NETWORK","MEDIA_ERR_DECODE","MEDIA_ERR_SRC_NOT_SUPPORTED","MEDIA_ERR_ENCRYPTED"],i.defaultMessages={1:"You aborted the media playback",2:"A network error caused the media download to fail part-way.",3:"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.",4:"The media could not be loaded, either because the server or network failed or because the format is not supported.",5:"The media is encrypted and we do not have the keys to decrypt it."},i.MEDIA_ERR_CUSTOM=0,i.prototype.MEDIA_ERR_CUSTOM=0,i.MEDIA_ERR_ABORTED=1,i.prototype.MEDIA_ERR_ABORTED=1,i.MEDIA_ERR_NETWORK=2,i.prototype.MEDIA_ERR_NETWORK=2,i.MEDIA_ERR_DECODE=3,i.prototype.MEDIA_ERR_DECODE=3,i.MEDIA_ERR_SRC_NOT_SUPPORTED=4,i.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED=4,i.MEDIA_ERR_ENCRYPTED=5,i.prototype.MEDIA_ERR_ENCRYPTED=5;function Yt(s){return["kind","label","language","id","inBandMetadataTrackDispatchType","mode","src"].reduce((e,t,i)=>(s[t]&&(e[t]=s[t]),e),{cues:s.cues&&Array.prototype.map.call(s.cues,function(e){return{startTime:e.startTime,endTime:e.endTime,text:e.text,id:e.id}})})}var Qt,Jt=function(e){var t=e.$$("track");let i=Array.prototype.map.call(t,e=>e.track);return Array.prototype.map.call(t,function(e){var t=Yt(e.track);return e.src&&(t.src=e.src),t}).concat(Array.prototype.filter.call(e.textTracks(),function(e){return-1===i.indexOf(e)}).map(Yt))},Zt=function(e,i){return e.forEach(function(e){let t=i.addRemoteTextTrack(e).track;!e.src&&e.cues&&e.cues.forEach(e=>t.addCue(e))}),i.textTracks()},ei=Yt;let ti="vjs-modal-dialog";class ii extends g{constructor(e,t){super(e,t),this.handleKeyDown_=e=>this.handleKeyDown(e),this.close_=e=>this.close(e),this.opened_=this.hasBeenOpened_=this.hasBeenFilled_=!1,this.closeable(!this.options_.uncloseable),this.content(this.options_.content),this.contentEl_=l("div",{className:ti+"-content"},{role:"document"}),this.descEl_=l("p",{className:ti+"-description vjs-control-text",id:this.el().getAttribute("aria-describedby")}),xe(this.descEl_,this.description()),this.el_.appendChild(this.descEl_),this.el_.appendChild(this.contentEl_)}createEl(){return super.createEl("div",{className:this.buildCSSClass(),tabIndex:-1},{"aria-describedby":this.id()+"_description","aria-hidden":"true","aria-label":this.label(),role:"dialog","aria-live":"polite"})}dispose(){this.contentEl_=null,this.descEl_=null,this.previouslyActiveEl_=null,super.dispose()}buildCSSClass(){return ti+" vjs-hidden "+super.buildCSSClass()}label(){return this.localize(this.options_.label||"Modal Window")}description(){let e=this.options_.description||this.localize("This is a modal window.");return this.closeable()&&(e+=" "+this.localize("This modal can be closed by pressing the Escape key or activating the close button.")),e}open(){var e;this.opened_?this.options_.fillAlways&&this.fill():(e=this.player(),this.trigger("beforemodalopen"),this.opened_=!0,!this.options_.fillAlways&&(this.hasBeenOpened_||this.hasBeenFilled_)||this.fill(),this.wasPlaying_=!e.paused(),this.options_.pauseOnOpen&&this.wasPlaying_&&e.pause(),this.on("keydown",this.handleKeyDown_),this.hadControls_=e.controls(),e.controls(!1),this.show(),this.conditionalFocus_(),this.el().setAttribute("aria-hidden","false"),this.trigger("modalopen"),this.hasBeenOpened_=!0)}opened(e){return"boolean"==typeof e&&this[e?"open":"close"](),this.opened_}close(){var e;this.opened_&&(e=this.player(),this.trigger("beforemodalclose"),this.opened_=!1,this.wasPlaying_&&this.options_.pauseOnOpen&&e.play(),this.off("keydown",this.handleKeyDown_),this.hadControls_&&e.controls(!0),this.hide(),this.el().setAttribute("aria-hidden","true"),this.trigger({type:"modalclose",bubbles:!0}),this.conditionalBlur_(),this.options_.temporary)&&this.dispose()}closeable(t){if("boolean"==typeof t){var i,t=this.closeable_=!!t;let e=this.getChild("closeButton");t&&!e&&(i=this.contentEl_,this.contentEl_=this.el_,e=this.addChild("closeButton",{controlText:"Close Modal Dialog"}),this.contentEl_=i,this.on(e,"close",this.close_)),!t&&e&&(this.off(e,"close",this.close_),this.removeChild(e),e.dispose())}return this.closeable_}fill(){this.fillWith(this.content())}fillWith(e){var t=this.contentEl(),i=t.parentNode,s=t.nextSibling,e=(this.trigger("beforemodalfill"),this.hasBeenFilled_=!0,i.removeChild(t),this.empty(),Xe(t,e),this.trigger("modalfill"),s?i.insertBefore(t,s):i.appendChild(t),this.getChild("closeButton"));e&&i.appendChild(e.el_),this.trigger("aftermodalfill")}empty(){this.trigger("beforemodalempty"),$e(this.contentEl()),this.trigger("modalempty")}content(e){return"undefined"!=typeof e&&(this.content_=e),this.content_}conditionalFocus_(){var e=document.activeElement,t=this.player_.el_;this.previouslyActiveEl_=null,!t.contains(e)&&t!==e||(this.previouslyActiveEl_=e,this.focus())}conditionalBlur_(){this.previouslyActiveEl_&&(this.previouslyActiveEl_.focus(),this.previouslyActiveEl_=null)}handleKeyDown(e){if(this.trigger({type:"modalKeydown",originalEvent:e,target:this,bubbles:!0}),e.stopPropagation(),"Escape"===e.key&&this.closeable())e.preventDefault(),this.close();else if("Tab"===e.key){var i=this.focusableEls_(),s=this.el_.querySelector(":focus");let t;for(let e=0;e(e instanceof window.HTMLAnchorElement||e instanceof window.HTMLAreaElement)&&e.hasAttribute("href")||(e instanceof window.HTMLInputElement||e instanceof window.HTMLSelectElement||e instanceof window.HTMLTextAreaElement||e instanceof window.HTMLButtonElement)&&!e.hasAttribute("disabled")||e instanceof window.HTMLIFrameElement||e instanceof window.HTMLObjectElement||e instanceof window.HTMLEmbedElement||e.hasAttribute("tabindex")&&-1!==e.getAttribute("tabindex")||e.hasAttribute("contenteditable"))}}ii.prototype.options_={pauseOnOpen:!0,temporary:!0},g.registerComponent("ModalDialog",ii);class si extends wt{constructor(t=[]){super(),this.tracks_=[],Object.defineProperty(this,"length",{get(){return this.tracks_.length}});for(let e=0;e{this.trigger({track:e,type:"labelchange",target:this})},Ct(e)&&e.addEventListener("labelchange",e.labelchange_)}removeTrack(i){let s;for(let e=0,t=this.length;e{this.changing_||(this.changing_=!0,ri(this,e),this.changing_=!1,this.trigger("change"))},e.addEventListener("enabledchange",e.enabledChange_))}removeTrack(e){super.removeTrack(e),e.removeEventListener&&e.enabledChange_&&(e.removeEventListener("enabledchange",e.enabledChange_),e.enabledChange_=null)}}function ai(t,i){for(let e=0;e{this.changing_||(this.changing_=!0,ai(this,e),this.changing_=!1,this.trigger("change"))},e.addEventListener("selectedchange",e.selectedChange_))}removeTrack(e){super.removeTrack(e),e.removeEventListener&&e.selectedChange_&&(e.removeEventListener("selectedchange",e.selectedChange_),e.selectedChange_=null)}}class li extends si{addTrack(e){super.addTrack(e),this.queueChange_||(this.queueChange_=()=>this.queueTrigger("change")),this.triggerSelectedlanguagechange||(this.triggerSelectedlanguagechange_=()=>this.trigger("selectedlanguagechange")),e.addEventListener("modechange",this.queueChange_);-1===["metadata","chapters"].indexOf(e.kind)&&e.addEventListener("modechange",this.triggerSelectedlanguagechange_)}removeTrack(e){super.removeTrack(e),e.removeEventListener&&(this.queueChange_&&e.removeEventListener("modechange",this.queueChange_),this.selectedlanguagechange_)&&e.removeEventListener("modechange",this.triggerSelectedlanguagechange_)}toJSON(){return this.tracks_.map(e=>e.toJSON())}}class di{constructor(e){di.prototype.setCues_.call(this,e),Object.defineProperty(this,"length",{get(){return this.length_}})}setCues_(e){var t=this.length||0;let i=0;function s(e){""+e in this||Object.defineProperty(this,""+e,{get(){return this.cues_[e]}})}var r=e.length;this.cues_=e,this.length_=e.length;if(t=e.length?{done:!0}:{done:!1,value:e[i++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Ii(e,t){(null==t||t>e.length)&&(t=e.length);for(var i=0,s=new Array(t);io.error(e)),window.console)&&window.console.groupEnd&&window.console.groupEnd(),i.flush()}function Bi(e,s){var t={uri:e};(e=yi(e))&&(t.cors=e),(e="use-credentials"===s.tech_.crossOrigin())&&(t.withCredentials=e),Pi(t,p(this,function(e,t,i){if(e)return o.error(e,t);s.loaded_=!0,"function"!=typeof window.WebVTT?s.tech_&&s.tech_.any(["vttjsloaded","vttjserror"],e=>{if("vttjserror"!==e.type)return Ui(i,s);o.error("vttjs failed to load, stopping trying to process "+s.src)}):Ui(i,s)}))}class Fi extends mi{constructor(e={}){if(!e.tech)throw new Error("A tech was not provided.");e=d(e,{kind:ci[e.kind]||"subtitles",language:e.language||e.srclang||""});let t=pi[e.mode]||"disabled",i=e.default,s=("metadata"!==e.kind&&"chapters"!==e.kind||(t="hidden"),super(e),this.tech_=e.tech,this.cues_=[],this.activeCues_=[],this.preload_=!1!==this.tech_.preloadTextTracks,new di(this.cues_)),n=new di(this.activeCues_),a=!1;this.timeupdateHandler=p(this,function(e={}){this.tech_.isDisposed()||(this.tech_.isReady_&&(this.activeCues=this.activeCues,a)&&(this.trigger("cuechange"),a=!1),"timeupdate"!==e.type&&(this.rvf_=this.tech_.requestVideoFrameCallback(this.timeupdateHandler)))});this.tech_.one("dispose",()=>{this.stopTracking()}),"disabled"!==t&&this.startTracking(),Object.defineProperties(this,{default:{get(){return i},set(){}},mode:{get(){return t},set(e){pi[e]&&t!==e&&(t=e,this.preload_||"disabled"===t||0!==this.cues.length||Bi(this.src,this),this.stopTracking(),"disabled"!==t&&this.startTracking(),this.trigger("modechange"))}},cues:{get(){return this.loaded_?s:null},set(){}},activeCues:{get(){if(!this.loaded_)return null;if(0!==this.cues.length){var i=this.tech_.currentTime(),s=[];for(let e=0,t=this.cues.length;e{t=Vi.LOADED,this.trigger({type:"load",target:this})})}}Vi.prototype.allowedEvents_={load:"load"},Vi.NONE=0,Vi.LOADING=1,Vi.LOADED=2,Vi.ERROR=3;let Hi={audio:{ListClass:ni,TrackClass:qi,capitalName:"Audio"},video:{ListClass:oi,TrackClass:ji,capitalName:"Video"},text:{ListClass:li,TrackClass:Fi,capitalName:"Text"}},zi=(Object.keys(Hi).forEach(function(e){Hi[e].getterName=e+"Tracks",Hi[e].privateName=e+"Tracks_"}),{remoteText:{ListClass:li,TrackClass:Fi,capitalName:"RemoteText",getterName:"remoteTextTracks",privateName:"remoteTextTracks_"},remoteTextEl:{ListClass:class{constructor(i=[]){this.trackElements_=[],Object.defineProperty(this,"length",{get(){return this.trackElements_.length}});for(let e=0,t=i.length;e]*>?)?/))[1]||o[2],t=t.substr(o.length),o):null);)"<"===o[0]?"/"===o[1]?h.length&&h[h.length-1]===o.substr(2).replace(">","")&&(h.pop(),d=d.parentNode):(s=Ki(o.substr(1,o.length-2)))?(i=e.document.createProcessingInstruction("timestamp",s),d.appendChild(i)):(s=o.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/))&&(r=s[1],n=s[3],a=void 0,a=Zi[r],i=a?(a=e.document.createElement(a),(r=ts[r])&&n&&(a[r]=n.trim()),a):null)&&(r=d,is[(n=i).localName]&&is[n.localName]!==r.localName||(s[2]&&((a=s[2].split(".")).forEach(function(e){var t=/^bg_/.test(e),e=t?e.slice(3):e;es.hasOwnProperty(e)&&(e=es[e],i.style[t?"background-color":"color"]=e)}),i.className=a.join(" ")),h.push(s[1]),d.appendChild(i),d=i)):d.appendChild(e.document.createTextNode((n=o,Ji.innerHTML=n,n=Ji.textContent,Ji.textContent="",n)));return l}var rs=[[1470,1470],[1472,1472],[1475,1475],[1478,1478],[1488,1514],[1520,1524],[1544,1544],[1547,1547],[1549,1549],[1563,1563],[1566,1610],[1645,1647],[1649,1749],[1765,1766],[1774,1775],[1786,1805],[1807,1808],[1810,1839],[1869,1957],[1969,1969],[1984,2026],[2036,2037],[2042,2042],[2048,2069],[2074,2074],[2084,2084],[2088,2088],[2096,2110],[2112,2136],[2142,2142],[2208,2208],[2210,2220],[8207,8207],[64285,64285],[64287,64296],[64298,64310],[64312,64316],[64318,64318],[64320,64321],[64323,64324],[64326,64449],[64467,64829],[64848,64911],[64914,64967],[65008,65020],[65136,65140],[65142,65276],[67584,67589],[67592,67592],[67594,67637],[67639,67640],[67644,67644],[67647,67669],[67671,67679],[67840,67867],[67872,67897],[67903,67903],[67968,68023],[68030,68031],[68096,68096],[68112,68115],[68117,68119],[68121,68147],[68160,68167],[68176,68184],[68192,68223],[68352,68405],[68416,68437],[68440,68466],[68472,68479],[68608,68680],[126464,126467],[126469,126495],[126497,126498],[126500,126500],[126503,126503],[126505,126514],[126516,126519],[126521,126521],[126523,126523],[126530,126530],[126535,126535],[126537,126537],[126539,126539],[126541,126543],[126545,126546],[126548,126548],[126551,126551],[126553,126553],[126555,126555],[126557,126557],[126559,126559],[126561,126562],[126564,126564],[126567,126570],[126572,126578],[126580,126583],[126585,126588],[126590,126590],[126592,126601],[126603,126619],[126625,126627],[126629,126633],[126635,126651],[1114109,1114109]];function ns(e){var t=[],i="";if(e&&e.childNodes)for(n(t,e);i=function e(t){var i,s,r;return t&&t.length?(s=(i=t.pop()).textContent||i.innerText)?(r=s.match(/^.*(\n|\r)/))?r[t.length=0]:s:"ruby"===i.tagName?e(t):i.childNodes?(n(t,i),e(t)):void 0:null}(t);)for(var s=0;s=i[0]&&e<=i[1])return 1}}(i.charCodeAt(s)))return"rtl";return"ltr";function n(e,t){for(var i=t.childNodes.length-1;0<=i;i--)e.push(t.childNodes[i])}}function as(){}function os(e,t,i){as.call(this),this.cue=t,this.cueDiv=ss(e,t.text);this.applyStyles({color:"rgba(255, 255, 255, 1)",backgroundColor:"rgba(0, 0, 0, 0.8)",position:"relative",left:0,right:0,top:0,bottom:0,display:"inline",writingMode:""===t.vertical?"horizontal-tb":"lr"===t.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext"},this.cueDiv),this.div=e.document.createElement("div"),e={direction:ns(this.cueDiv),writingMode:""===t.vertical?"horizontal-tb":"lr"===t.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext",textAlign:"middle"===t.align?"center":t.align,font:i.font,whiteSpace:"pre-line",position:"absolute"},this.applyStyles(e),this.div.appendChild(this.cueDiv);var s=0;switch(t.positionAlign){case"start":case"line-left":s=t.position;break;case"center":s=t.position-t.size/2;break;case"end":case"line-right":s=t.position-t.size}""===t.vertical?this.applyStyles({left:this.formatStyle(s,"%"),width:this.formatStyle(t.size,"%")}):this.applyStyles({top:this.formatStyle(s,"%"),height:this.formatStyle(t.size,"%")}),this.move=function(e){this.applyStyles({top:this.formatStyle(e.top,"px"),bottom:this.formatStyle(e.bottom,"px"),left:this.formatStyle(e.left,"px"),right:this.formatStyle(e.right,"px"),height:this.formatStyle(e.height,"px"),width:this.formatStyle(e.width,"px")})}}function _(e){var t,i,s,r;e.div&&(t=e.div.offsetHeight,i=e.div.offsetWidth,s=e.div.offsetTop,r=(r=(r=e.div.childNodes)&&r[0])&&r.getClientRects&&r.getClientRects(),e=e.div.getBoundingClientRect(),r=r?Math.max(r[0]&&r[0].height||0,e.height/r.length):0),this.left=e.left,this.right=e.right,this.top=e.top||s,this.height=e.height||t,this.bottom=e.bottom||s+(e.height||t),this.width=e.width||i,this.lineHeight=void 0!==r?r:e.lineHeight}function ls(e,t,o,l){var i,s=new _(t),r=t.cue,n=function(e){if("number"==typeof e.line&&(e.snapToLines||0<=e.line&&e.line<=100))return e.line;if(!e.track||!e.track.textTrackList||!e.track.textTrackList.mediaElement)return-1;for(var t=e.track,i=t.textTrackList,s=0,r=0;ru&&(h=h<0?-1:1,h*=Math.ceil(u/d)*d),n<0&&(h+=""===r.vertical?o.height:o.width,a=a.reverse()),s.move(c,h)}else{var p=s.lineHeight/o.height*100;switch(r.lineAlign){case"center":n-=p/2;break;case"end":n-=p}switch(r.vertical){case"":t.applyStyles({top:t.formatStyle(n,"%")});break;case"rl":t.applyStyles({left:t.formatStyle(n,"%")});break;case"lr":t.applyStyles({right:t.formatStyle(n,"%")})}a=["+y","-x","+x","-y"],s=new _(t)}u=function(e,t){for(var i,s=new _(e),r=1,n=0;ne.left&&this.tope.top},_.prototype.overlapsAny=function(e){for(var t=0;t=e.top&&this.bottom<=e.bottom&&this.left>=e.left&&this.right<=e.right},_.prototype.overlapsOppositeAxis=function(e,t){switch(t){case"+x":return this.lefte.right;case"+y":return this.tope.bottom}},_.prototype.intersectPercentage=function(e){return Math.max(0,Math.min(this.right,e.right)-Math.max(this.left,e.left))*Math.max(0,Math.min(this.bottom,e.bottom)-Math.max(this.top,e.top))/(this.height*this.width)},_.prototype.toCSSCompatValues=function(e){return{top:this.top-e.top,bottom:e.bottom-this.bottom,left:this.left-e.left,right:e.right-this.right,height:this.height,width:this.width}},_.getSimpleBoxPosition=function(e){var t=e.div?e.div.offsetHeight:e.tagName?e.offsetHeight:0,i=e.div?e.div.offsetWidth:e.tagName?e.offsetWidth:0,s=e.div?e.div.offsetTop:e.tagName?e.offsetTop:0;return{left:(e=e.div?e.div.getBoundingClientRect():e.tagName?e.getBoundingClientRect():e).left,right:e.right,top:e.top||s,height:e.height||t,bottom:e.bottom||s+(e.height||t),width:e.width||i}},ds.StringDecoder=function(){return{decode:function(e){if(!e)return"";if("string"!=typeof e)throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(e))}}},ds.convertCueToDOMTree=function(e,t){return e&&t?ss(e,t):null};ds.processCues=function(e,t,i){if(!e||!t||!i)return null;for(;i.firstChild;)i.removeChild(i.firstChild);var s=e.document.createElement("div");if(s.style.position="absolute",s.style.left="0",s.style.right="0",s.style.top="0",s.style.bottom="0",s.style.margin="1.5%",i.appendChild(s),function(e){for(var t=0;tthis.onDurationChange(e),this.trackProgress_=e=>this.trackProgress(e),this.trackCurrentTime_=e=>this.trackCurrentTime(e),this.stopTrackingCurrentTime_=e=>this.stopTrackingCurrentTime(e),this.disposeSourceHandler_=e=>this.disposeSourceHandler(e),this.queuedHanders_=new Set,this.hasStarted_=!1,this.on("playing",function(){this.hasStarted_=!0}),this.on("loadstart",function(){this.hasStarted_=!1}),a.names.forEach(e=>{e=a[e];t&&t[e.getterName]&&(this[e.privateName]=t[e.getterName])}),this.featuresProgressEvents||this.manualProgressOn(),this.featuresTimeupdateEvents||this.manualTimeUpdatesOn(),["Text","Audio","Video"].forEach(e=>{!1===t[`native${e}Tracks`]&&(this[`featuresNative${e}Tracks`]=!1)}),!1===t.nativeCaptions||!1===t.nativeTextTracks?this.featuresNativeTextTracks=!1:!0!==t.nativeCaptions&&!0!==t.nativeTextTracks||(this.featuresNativeTextTracks=!0),this.featuresNativeTextTracks||this.emulateTextTracks(),this.preloadTextTracks=!1!==t.preloadTextTracks,this.autoRemoteTextTracks_=new a.text.ListClass,this.initTrackListeners(),t.nativeControlsForTouch||this.emitTapEvents(),this.constructor&&(this.name_=this.constructor.name||"Unknown Tech")}triggerSourceset(e){this.isReady_||this.one("ready",()=>this.setTimeout(()=>this.triggerSourceset(e),1)),this.trigger({src:e,type:"sourceset"})}manualProgressOn(){this.on("durationchange",this.onDurationChange_),this.manualProgress=!0,this.one("ready",this.trackProgress_)}manualProgressOff(){this.manualProgress=!1,this.stopTrackingProgress(),this.off("durationchange",this.onDurationChange_)}trackProgress(e){this.stopTrackingProgress(),this.progressInterval=this.setInterval(p(this,function(){var e=this.bufferedPercent();this.bufferedPercent_!==e&&this.trigger("progress"),1===(this.bufferedPercent_=e)&&this.stopTrackingProgress()}),500)}onDurationChange(e){this.duration_=this.duration()}buffered(){return jt(0,0)}bufferedPercent(){return Gt(this.buffered(),this.duration_)}stopTrackingProgress(){this.clearInterval(this.progressInterval)}manualTimeUpdatesOn(){this.manualTimeUpdates=!0,this.on("play",this.trackCurrentTime_),this.on("pause",this.stopTrackingCurrentTime_)}manualTimeUpdatesOff(){this.manualTimeUpdates=!1,this.stopTrackingCurrentTime(),this.off("play",this.trackCurrentTime_),this.off("pause",this.stopTrackingCurrentTime_)}trackCurrentTime(){this.currentTimeInterval&&this.stopTrackingCurrentTime(),this.currentTimeInterval=this.setInterval(function(){this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},250)}stopTrackingCurrentTime(){this.clearInterval(this.currentTimeInterval),this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})}dispose(){this.clearTracks(Hi.names),this.manualProgress&&this.manualProgressOff(),this.manualTimeUpdates&&this.manualTimeUpdatesOff(),super.dispose()}clearTracks(e){(e=[].concat(e)).forEach(e=>{var t=this[e+"Tracks"]()||[];let i=t.length;for(;i--;){var s=t[i];"text"===e&&this.removeRemoteTextTrack(s),t.removeTrack(s)}})}cleanupAutoTextTracks(){var e=this.autoRemoteTextTracks_||[];let t=e.length;for(;t--;){var i=e[t];this.removeRemoteTextTrack(i)}}reset(){}crossOrigin(){}setCrossOrigin(){}error(e){return void 0!==e&&(this.error_=new i(e),this.trigger("error")),this.error_}played(){return this.hasStarted_?jt(0,0):jt()}play(){}setScrubbing(e){}scrubbing(){}setCurrentTime(e){this.manualTimeUpdates&&this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})}initTrackListeners(){Hi.names.forEach(e=>{var t=Hi[e];let i=()=>{this.trigger(e+"trackchange")},s=this[t.getterName]();s.addEventListener("removetrack",i),s.addEventListener("addtrack",i),this.on("dispose",()=>{s.removeEventListener("removetrack",i),s.removeEventListener("addtrack",i)})})}addWebVttScript_(){if(!window.WebVTT)if(document.body.contains(this.el()))if(!this.options_["vtt.js"]&&Q(vs)&&0{this.trigger("vttjsloaded")},e.onerror=()=>{this.trigger("vttjserror")},this.on("dispose",()=>{e.onload=null,e.onerror=null}),window.WebVTT=!0,this.el().parentNode.appendChild(e)}else this.ready(this.addWebVttScript_)}emulateTextTracks(){let i=this.textTracks(),e=this.remoteTextTracks(),t=e=>i.addTrack(e.track),s=e=>i.removeTrack(e.track),r=(e.on("addtrack",t),e.on("removetrack",s),this.addWebVttScript_(),()=>this.trigger("texttrackchange")),n=()=>{r();for(let e=0;ethis.autoRemoteTextTracks_.addTrack(i.track)),i}removeRemoteTextTrack(e){var t=this.remoteTextTrackEls().getTrackElementByTrack_(e);this.remoteTextTrackEls().removeTrackElement_(t),this.remoteTextTracks().removeTrack(e),this.autoRemoteTextTracks_.removeTrack(e)}getVideoPlaybackQuality(){return{}}requestPictureInPicture(){return Promise.reject()}disablePictureInPicture(){return!0}setDisablePictureInPicture(){}requestVideoFrameCallback(e){let t=lt++;return!this.isReady_||this.paused()?(this.queuedHanders_.add(t),this.one("playing",()=>{this.queuedHanders_.has(t)&&(this.queuedHanders_.delete(t),e())})):this.requestNamedAnimationFrame(t,e),t}cancelVideoFrameCallback(e){this.queuedHanders_.has(e)?this.queuedHanders_.delete(e):this.cancelNamedAnimationFrame(e)}setPoster(){}playsinline(){}setPlaysinline(){}overrideNativeAudioTracks(e){}overrideNativeVideoTracks(e){}canPlayType(e){return""}static canPlayType(e){return""}static canPlaySource(e,t){return v.canPlayType(e.type)}static isTech(e){return e.prototype instanceof v||e instanceof v||e===v}static registerTech(e,t){if(v.techs_||(v.techs_={}),!v.isTech(t))throw new Error(`Tech ${e} must be a Tech`);if(!v.canPlayType)throw new Error("Techs must have a static canPlayType method on them");if(v.canPlaySource)return e=m(e),v.techs_[e]=t,v.techs_[Mt(e)]=t,"Tech"!==e&&v.defaultTechOrder_.push(e),t;throw new Error("Techs must have a static canPlaySource method on them")}static getTech(e){if(e)return v.techs_&&v.techs_[e]?v.techs_[e]:(e=m(e),window&&window.videojs&&window.videojs[e]?(o.warn(`The ${e} tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)`),window.videojs[e]):void 0)}}a.names.forEach(function(e){let t=a[e];v.prototype[t.getterName]=function(){return this[t.privateName]=this[t.privateName]||new t.ListClass,this[t.privateName]}}),v.prototype.featuresVolumeControl=!0,v.prototype.featuresMuteControl=!0,v.prototype.featuresFullscreenResize=!1,v.prototype.featuresPlaybackRate=!1,v.prototype.featuresProgressEvents=!1,v.prototype.featuresSourceset=!1,v.prototype.featuresTimeupdateEvents=!1,v.prototype.featuresNativeTextTracks=!1,v.prototype.featuresVideoFrameCallback=!1,v.withSourceHandlers=function(r){r.registerSourceHandler=function(e,t){let i=r.sourceHandlers;i=i||(r.sourceHandlers=[]),void 0===t&&(t=i.length),i.splice(t,0,e)},r.canPlayType=function(t){var i,s=r.sourceHandlers||[];for(let e=0;efunction s(r={},e=[],n,a,o=[],l=!1){let[t,...d]=e;if("string"==typeof t)s(r,bs[t],n,a,o,l);else if(t){let i=As(a,t);if(!i.setSource)return o.push(i),s(r,d,n,a,o,l);i.setSource(Object.assign({},r),function(e,t){if(e)return s(r,d,n,a,o,l);o.push(i),s(t,r.type===t.type?d:bs[t.type],n,a,o,l)})}else d.length?s(r,d,n,a,o,l):l?n(r,o):s(r,bs["*"],n,a,o,!0)}(t,bs[t.type],i,e),1)}function Es(e,t,i,s=null){var r="call"+m(i),r=e.reduce(xs(r),s),s=r===Ss,t=s?null:t[i](r),n=e,a=i,o=t,l=s;for(let e=n.length-1;0<=e;e--){var d=n[e];d[a]&&d[a](l,o)}return t}let Cs={buffered:1,currentTime:1,duration:1,muted:1,played:1,paused:1,seekable:1,volume:1,ended:1},ks={setCurrentTime:1,setMuted:1,setVolume:1},Is={play:1,pause:1};function xs(i){return(e,t)=>e===Ss?Ss:t[i]?t[i](e):e}function As(e,t){var i=Ts[e.id()];let s=null;if(null==i)s=t(e),Ts[e.id()]=[[t,s]];else{for(let e=0;e{this.focus(this.updateFocusableComponents()[0])}),this.player_.on("modalclose",()=>{this.refocusComponent()}),this.player_.on("focusin",this.handlePlayerFocus_.bind(this)),this.player_.on("focusout",this.handlePlayerBlur_.bind(this)),this.isListening_=!0,this.player_.errorDisplay&&this.player_.errorDisplay.on("aftermodalfill",()=>{this.updateFocusableComponents(),this.focusableComponents.length&&(1{if(e.hasOwnProperty("el_")){if(e.getIsFocusable&&e.getIsAvailableToBeFocused&&e.getIsFocusable()&&e.getIsAvailableToBeFocused(e.el()))return void i.push(e);e.hasOwnProperty("children_")&&0{i.push({name:()=>"ModalButton"+(e+1),el:()=>t,getPositions:()=>{var e=t.getBoundingClientRect();return{boundingClientRect:{x:e.x,y:e.y,width:e.width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left},center:{x:e.left+e.width/2,y:e.top+e.height/2,width:0,height:0,top:e.top+e.height/2,right:e.left+e.width/2,bottom:e.top+e.height/2,left:e.left+e.width/2}}},getIsAvailableToBeFocused:()=>!0,getIsFocusable:e=>!0,focus:()=>t.focus()})})}),this.focusableComponents=i,this.focusableComponents}findSuitableDOMChild(e){return e.el()?function t(i){if(e.getIsFocusable(i)&&e.getIsAvailableToBeFocused(i))return i;for(let e=0;ee!==s&&this.isInDirection_(t.boundingClientRect,e.getPositions().boundingClientRect,i)),e=this.findBestCandidate_(t.center,e,i);e?this.focus(e):this.trigger({type:"endOfFocusableComponents",direction:i,focusedComponent:s})}}findBestCandidate_(e,t,i){let s=1/0,r=null;for(var n of t){var a=n.getPositions().center,a=this.calculateDistance_(e,a,i);a=e.right;case"left":return t.right<=e.left;case"down":return t.top>=e.bottom;case"up":return t.bottom<=e.top;default:return!1}}refocusComponent(){if(this.lastFocusedComponent_){this.player_.userActive()||this.player_.userActive(!0),this.updateFocusableComponents();for(let e=0;ethis.handleMouseOver(e),this.handleMouseOut_=e=>this.handleMouseOut(e),this.handleClick_=e=>this.handleClick(e),this.handleKeyDown_=e=>this.handleKeyDown(e),this.emitTapEvents(),this.enable()}createEl(e="div",t={},i={}){t=Object.assign({className:this.buildCSSClass(),tabIndex:0},t),"button"===e&&o.error(`Creating a ClickableComponent with an HTML element of ${e} is not supported; use a Button instead.`),i=Object.assign({role:"button"},i),this.tabIndex_=t.tabIndex;e=l(e,t,i);return this.player_.options_.experimentalSvgIcons||e.appendChild(l("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),this.createControlTextEl(e),e}dispose(){this.controlTextEl_=null,super.dispose()}createControlTextEl(e){return this.controlTextEl_=l("span",{className:"vjs-control-text"},{"aria-live":"polite"}),e&&e.appendChild(this.controlTextEl_),this.controlText(this.controlText_,e),this.controlTextEl_}controlText(e,t=this.el()){if(void 0===e)return this.controlText_||"Need Text";var i=this.localize(e);this.controlText_=e,xe(this.controlTextEl_,i),this.nonIconControl||this.player_.options_.noUITitleAttributes||t.setAttribute("title",i)}buildCSSClass(){return"vjs-control vjs-button "+super.buildCSSClass()}enable(){this.enabled_||(this.enabled_=!0,this.removeClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","false"),"undefined"!=typeof this.tabIndex_&&this.el_.setAttribute("tabIndex",this.tabIndex_),this.on(["tap","click"],this.handleClick_),this.on("keydown",this.handleKeyDown_))}disable(){this.enabled_=!1,this.addClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","true"),"undefined"!=typeof this.tabIndex_&&this.el_.removeAttribute("tabIndex"),this.off("mouseover",this.handleMouseOver_),this.off("mouseout",this.handleMouseOut_),this.off(["tap","click"],this.handleClick_),this.off("keydown",this.handleKeyDown_)}handleLanguagechange(){this.controlText(this.controlText_)}handleClick(e){this.options_.clickHandler&&this.options_.clickHandler.call(this,arguments)}handleKeyDown(e){" "===e.key||"Enter"===e.key?(e.preventDefault(),e.stopPropagation(),this.trigger("click")):super.handleKeyDown(e)}}g.registerComponent("ClickableComponent",Us);class Bs extends Us{constructor(e,t){super(e,t),this.update(),this.update_=e=>this.update(e),e.on("posterchange",this.update_)}dispose(){this.player().off("posterchange",this.update_),super.dispose()}createEl(){return l("div",{className:"vjs-poster"})}crossOrigin(e){if("undefined"==typeof e)return this.$("img")?this.$("img").crossOrigin:this.player_.tech_&&this.player_.tech_.isReady_?this.player_.crossOrigin():this.player_.options_.crossOrigin||this.player_.options_.crossorigin||null;null!==e&&"anonymous"!==e&&"use-credentials"!==e?this.player_.log.warn(`crossOrigin must be null, "anonymous" or "use-credentials", given "${e}"`):this.$("img")&&(this.$("img").crossOrigin=e)}update(e){var t=this.player().poster();this.setSrc(t),t?this.show():this.hide()}setSrc(e){e?(this.$("img")||this.el_.appendChild(l("picture",{className:"vjs-poster",tabIndex:-1},{},l("img",{loading:"lazy",crossOrigin:this.crossOrigin()},{alt:""}))),this.$("img").src=e):this.el_.textContent=""}handleClick(e){this.player_.controls()&&(this.player_.tech(!0)&&this.player_.tech(!0).focus(),this.player_.paused()?Kt(this.player_.play()):this.player_.pause())}}Bs.prototype.crossorigin=Bs.prototype.crossOrigin,g.registerComponent("PosterImage",Bs);let Fs={monospace:"monospace",sansSerif:"sans-serif",serif:"serif",monospaceSansSerif:'"Andale Mono", "Lucida Console", monospace',monospaceSerif:'"Courier New", monospace',proportionalSansSerif:"sans-serif",proportionalSerif:"serif",casual:'"Comic Sans MS", Impact, fantasy',script:'"Monotype Corsiva", cursive',smallcaps:'"Andale Mono", "Lucida Console", monospace, sans-serif'};function qs(e,t){let i;if(4===e.length)i=e[1]+e[1]+e[2]+e[2]+e[3]+e[3];else{if(7!==e.length)throw new Error("Invalid color code provided, "+e+"; must be formatted as e.g. #f0e or #f604e2.");i=e.slice(1)}return"rgba("+parseInt(i.slice(0,2),16)+","+parseInt(i.slice(2,4),16)+","+parseInt(i.slice(4,6),16)+","+t+")"}function js(e,t,i){try{e.style[t]=i}catch(e){}}function Vs(e){return e?e+"px":""}class Hs extends g{constructor(s,e,t){super(s,e,t);e=e=>this.updateDisplay(e);let r=e=>{this.updateDisplayOverlay(),this.updateDisplay(e)};s.on("loadstart",e=>this.toggleDisplay(e)),s.on("useractive",e),s.on("userinactive",e),s.on("texttrackchange",e),s.on("loadedmetadata",e=>{this.updateDisplayOverlay(),this.preselectTrack(e)}),s.ready(p(this,function(){if(s.tech_&&s.tech_.featuresNativeTextTracks)this.hide();else{s.on("fullscreenchange",r),s.on("playerresize",r);let e=window.screen.orientation||window,t=window.screen.orientation?"change":"orientationchange";e.addEventListener(t,r),s.on("dispose",()=>e.removeEventListener(t,r));var i=this.options_.playerOptions.tracks||[];for(let e=0;e{var t;e.style.inset&&3===(t=e.style.inset.split(" ")).length&&Object.assign(e.style,{top:t[0],right:t[1],bottom:t[2],left:"unset"})}))}}updateDisplayOverlay(){if(this.player_.videoHeight()&&window.CSS.supports("inset-inline: 10px")){var i=this.player_.currentWidth(),s=this.player_.currentHeight(),r=i/s,n=this.player_.videoWidth()/this.player_.videoHeight();let e=0,t=0;.1!e.activeCues)){var t=[];for(let e=0;ethis.handleMouseDown(e))}buildCSSClass(){return"vjs-big-play-button"}handleClick(t){var i=this.player_.play();if("tap"===t.type||this.mouseused_&&"clientX"in t&&"clientY"in t)Kt(i),this.player_.tech(!0)&&this.player_.tech(!0).focus();else{var t=this.player_.getChild("controlBar");let e=t&&t.getChild("playToggle");e?(t=()=>e.focus(),Xt(i)?i.then(t,()=>{}):this.setTimeout(t,1)):this.player_.tech(!0).focus()}}handleKeyDown(e){this.mouseused_=!1,super.handleKeyDown(e)}handleMouseDown(e){this.mouseused_=!0}}$s.prototype.controlText_="Play Video",g.registerComponent("BigPlayButton",$s);class Ws extends s{constructor(e,t){super(e,t),this.setIcon("cancel"),this.controlText(t&&t.controlText||this.localize("Close"))}buildCSSClass(){return"vjs-close-button "+super.buildCSSClass()}handleClick(e){this.trigger({type:"close",bubbles:!1})}handleKeyDown(e){"Escape"===e.key?(e.preventDefault(),e.stopPropagation(),this.trigger("click")):super.handleKeyDown(e)}}g.registerComponent("CloseButton",Ws);class Gs extends s{constructor(e,t={}){super(e,t),t.replay=void 0===t.replay||t.replay,this.setIcon("play"),this.on(e,"play",e=>this.handlePlay(e)),this.on(e,"pause",e=>this.handlePause(e)),t.replay&&this.on(e,"ended",e=>this.handleEnded(e))}buildCSSClass(){return"vjs-play-control "+super.buildCSSClass()}handleClick(e){this.player_.paused()?Kt(this.player_.play()):this.player_.pause()}handleSeeked(e){this.removeClass("vjs-ended"),this.player_.paused()?this.handlePause(e):this.handlePlay(e)}handlePlay(e){this.removeClass("vjs-ended","vjs-paused"),this.addClass("vjs-playing"),this.setIcon("pause"),this.controlText("Pause")}handlePause(e){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.setIcon("play"),this.controlText("Play")}handleEnded(e){this.removeClass("vjs-playing"),this.addClass("vjs-ended"),this.setIcon("replay"),this.controlText("Replay"),this.one(this.player_,"seeked",e=>this.handleSeeked(e))}}Gs.prototype.controlText_="Play",g.registerComponent("PlayToggle",Gs);class Xs extends g{constructor(e,t){super(e,t),this.on(e,["timeupdate","ended","seeking"],e=>this.update(e)),this.updateTextNode_()}createEl(){var e=this.buildCSSClass(),t=super.createEl("div",{className:e+" vjs-time-control vjs-control"}),i=l("span",{className:"vjs-control-text",textContent:this.localize(this.labelText_)+" "},{role:"presentation"});return t.appendChild(i),this.contentEl_=l("span",{className:e+"-display"},{role:"presentation"}),t.appendChild(this.contentEl_),t}dispose(){this.contentEl_=null,this.textNode_=null,super.dispose()}update(e){!this.player_.options_.enableSmoothSeeking&&"seeking"===e.type||this.updateContent(e)}updateTextNode_(e=0){e=Wt(e),this.formattedTime_!==e&&(this.formattedTime_=e,this.requestNamedAnimationFrame("TimeDisplay#updateTextNode_",()=>{if(this.contentEl_){let e=this.textNode_;e&&this.contentEl_.firstChild!==e&&(e=null,o.warn("TimeDisplay#updateTextnode_: Prevented replacement of text node element since it was no longer a child of this node. Appending a new node instead.")),this.textNode_=document.createTextNode(this.formattedTime_),this.textNode_&&(e?this.contentEl_.replaceChild(this.textNode_,e):this.contentEl_.appendChild(this.textNode_))}}))}updateContent(e){}}Xs.prototype.labelText_="Time",Xs.prototype.controlText_="Time",g.registerComponent("TimeDisplay",Xs);class Ks extends Xs{buildCSSClass(){return"vjs-current-time"}updateContent(e){let t;t=this.player_.ended()?this.player_.duration():e&&e.target&&"function"==typeof e.target.pendingSeekTime?e.target.pendingSeekTime():this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime(),this.updateTextNode_(t)}}Ks.prototype.labelText_="Current Time",Ks.prototype.controlText_="Current Time",g.registerComponent("CurrentTimeDisplay",Ks);class Ys extends Xs{constructor(e,t){super(e,t);t=e=>this.updateContent(e);this.on(e,"durationchange",t),this.on(e,"loadstart",t),this.on(e,"loadedmetadata",t)}buildCSSClass(){return"vjs-duration"}updateContent(e){var t=this.player_.duration();this.updateTextNode_(t)}}Ys.prototype.labelText_="Duration",Ys.prototype.controlText_="Duration",g.registerComponent("DurationDisplay",Ys);class Qs extends g{createEl(){var e=super.createEl("div",{className:"vjs-time-control vjs-time-divider"},{"aria-hidden":!0}),t=super.createEl("div"),i=super.createEl("span",{textContent:"/"});return t.appendChild(i),e.appendChild(t),e}}g.registerComponent("TimeDivider",Qs);class Js extends Xs{constructor(e,t){super(e,t),this.on(e,"durationchange",e=>this.updateContent(e))}buildCSSClass(){return"vjs-remaining-time"}createEl(){var e=super.createEl();return!1!==this.options_.displayNegative&&e.insertBefore(l("span",{},{"aria-hidden":!0},"-"),this.contentEl_),e}updateContent(e){if("number"==typeof this.player_.duration()){let e;e=this.player_.ended()?0:this.player_.remainingTimeDisplay?this.player_.remainingTimeDisplay():this.player_.remainingTime(),this.updateTextNode_(e)}}}Js.prototype.labelText_="Remaining Time",Js.prototype.controlText_="Remaining Time",g.registerComponent("RemainingTimeDisplay",Js);class Zs extends g{constructor(e,t){super(e,t),this.updateShowing(),this.on(this.player(),"durationchange",e=>this.updateShowing(e))}createEl(){var e=super.createEl("div",{className:"vjs-live-control vjs-control"});return this.contentEl_=l("div",{className:"vjs-live-display"},{"aria-live":"off"}),this.contentEl_.appendChild(l("span",{className:"vjs-control-text",textContent:this.localize("Stream Type")+" "})),this.contentEl_.appendChild(document.createTextNode(this.localize("LIVE"))),e.appendChild(this.contentEl_),e}dispose(){this.contentEl_=null,super.dispose()}updateShowing(e){this.player().duration()===1/0?this.show():this.hide()}}g.registerComponent("LiveDisplay",Zs);class er extends s{constructor(e,t){super(e,t),this.updateLiveEdgeStatus(),this.player_.liveTracker&&(this.updateLiveEdgeStatusHandler_=e=>this.updateLiveEdgeStatus(e),this.on(this.player_.liveTracker,"liveedgechange",this.updateLiveEdgeStatusHandler_))}createEl(){var e=super.createEl("button",{className:"vjs-seek-to-live-control vjs-control"});return this.setIcon("circle",e),this.textEl_=l("span",{className:"vjs-seek-to-live-text",textContent:this.localize("LIVE")},{"aria-hidden":"true"}),e.appendChild(this.textEl_),e}updateLiveEdgeStatus(){!this.player_.liveTracker||this.player_.liveTracker.atLiveEdge()?(this.setAttribute("aria-disabled",!0),this.addClass("vjs-at-live-edge"),this.controlText("Seek to live, currently playing live")):(this.setAttribute("aria-disabled",!1),this.removeClass("vjs-at-live-edge"),this.controlText("Seek to live, currently behind live"))}handleClick(){this.player_.liveTracker.seekToLiveEdge()}dispose(){this.player_.liveTracker&&this.off(this.player_.liveTracker,"liveedgechange",this.updateLiveEdgeStatusHandler_),this.textEl_=null,super.dispose()}}function tr(e,t,i){return e=Number(e),Math.min(i,Math.max(t,isNaN(e)?t:e))}er.prototype.controlText_="Seek to live, currently playing live",g.registerComponent("SeekToLive",er);$i=Object.freeze({__proto__:null,clamp:tr});class ir extends g{constructor(e,t){super(e,t),this.handleMouseDown_=e=>this.handleMouseDown(e),this.handleMouseUp_=e=>this.handleMouseUp(e),this.handleKeyDown_=e=>this.handleKeyDown(e),this.handleClick_=e=>this.handleClick(e),this.handleMouseMove_=e=>this.handleMouseMove(e),this.update_=e=>this.update(e),this.bar=this.getChild(this.options_.barName),this.vertical(!!this.options_.vertical),this.enable()}enabled(){return this.enabled_}enable(){this.enabled()||(this.on("mousedown",this.handleMouseDown_),this.on("touchstart",this.handleMouseDown_),this.on("keydown",this.handleKeyDown_),this.on("click",this.handleClick_),this.on(this.player_,"controlsvisible",this.update),this.playerEvent&&this.on(this.player_,this.playerEvent,this.update),this.removeClass("disabled"),this.setAttribute("tabindex",0),this.enabled_=!0)}disable(){var e;this.enabled()&&(e=this.bar.el_.ownerDocument,this.off("mousedown",this.handleMouseDown_),this.off("touchstart",this.handleMouseDown_),this.off("keydown",this.handleKeyDown_),this.off("click",this.handleClick_),this.off(this.player_,"controlsvisible",this.update_),this.off(e,"mousemove",this.handleMouseMove_),this.off(e,"mouseup",this.handleMouseUp_),this.off(e,"touchmove",this.handleMouseMove_),this.off(e,"touchend",this.handleMouseUp_),this.removeAttribute("tabindex"),this.addClass("disabled"),this.playerEvent&&this.off(this.player_,this.playerEvent,this.update),this.enabled_=!1)}createEl(e,t={},i={}){return t.className=t.className+" vjs-slider",t=Object.assign({tabIndex:0},t),i=Object.assign({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100},i),super.createEl(e,t,i)}handleMouseDown(e){var t=this.bar.el_.ownerDocument;"mousedown"===e.type&&e.preventDefault(),"touchstart"!==e.type||le||e.preventDefault(),Fe(),this.addClass("vjs-sliding"),this.trigger("slideractive"),this.on(t,"mousemove",this.handleMouseMove_),this.on(t,"mouseup",this.handleMouseUp_),this.on(t,"touchmove",this.handleMouseMove_),this.on(t,"touchend",this.handleMouseUp_),this.handleMouseMove(e,!0)}handleMouseMove(e){}handleMouseUp(e){var t=this.bar.el_.ownerDocument;qe(),this.removeClass("vjs-sliding"),this.trigger("sliderinactive"),this.off(t,"mousemove",this.handleMouseMove_),this.off(t,"mouseup",this.handleMouseUp_),this.off(t,"touchmove",this.handleMouseMove_),this.off(t,"touchend",this.handleMouseUp_),this.update()}update(){if(this.el_&&this.bar){let t=this.getProgress();return t!==this.progress_&&(this.progress_=t,this.requestNamedAnimationFrame("Slider#update",()=>{var e=this.vertical()?"height":"width";this.bar.el().style[e]=(100*t).toFixed(2)+"%"})),t}}getProgress(){return Number(tr(this.getPercent(),0,1).toFixed(4))}calculateDistance(e){e=He(this.el_,e);return this.vertical()?e.y:e.x}handleKeyDown(e){var t=this.options_.playerOptions.spatialNavigation,i=t&&t.enabled,t=t&&t.horizontalSeek;i?t&&"ArrowLeft"===e.key||!t&&"ArrowDown"===e.key?(e.preventDefault(),e.stopPropagation(),this.stepBack()):t&&"ArrowRight"===e.key||!t&&"ArrowUp"===e.key?(e.preventDefault(),e.stopPropagation(),this.stepForward()):(this.pendingSeekTime()&&(this.pendingSeekTime(null),this.userSeek_(this.player_.currentTime())),super.handleKeyDown(e)):"ArrowLeft"===e.key||"ArrowDown"===e.key?(e.preventDefault(),e.stopPropagation(),this.stepBack()):"ArrowUp"===e.key||"ArrowRight"===e.key?(e.preventDefault(),e.stopPropagation(),this.stepForward()):super.handleKeyDown(e)}handleClick(e){e.stopPropagation(),e.preventDefault()}vertical(e){if(void 0===e)return this.vertical_||!1;this.vertical_=!!e,this.vertical_?this.addClass("vjs-slider-vertical"):this.addClass("vjs-slider-horizontal")}}g.registerComponent("Slider",ir);let sr=(e,t)=>tr(e/t*100,0,100).toFixed(2)+"%";class rr extends g{constructor(e,t){super(e,t),this.partEls_=[],this.on(e,"progress",e=>this.update(e))}createEl(){var e=super.createEl("div",{className:"vjs-load-progress"}),t=l("span",{className:"vjs-control-text"}),i=l("span",{textContent:this.localize("Loaded")}),s=document.createTextNode(": ");return this.percentageEl_=l("span",{className:"vjs-control-text-loaded-percentage",textContent:"0%"}),e.appendChild(t),t.appendChild(i),t.appendChild(s),t.appendChild(this.percentageEl_),e}dispose(){this.partEls_=null,this.percentageEl_=null,super.dispose()}update(e){this.requestNamedAnimationFrame("LoadProgressBar#update",()=>{var e=this.player_.liveTracker,i=this.player_.buffered(),e=e&&e.isLive()?e.seekableEnd():this.player_.duration(),s=this.player_.bufferedEnd(),r=this.partEls_,e=sr(s,e);this.percent_!==e&&(this.el_.style.width=e,xe(this.percentageEl_,e),this.percent_=e);for(let t=0;ti.length;e--)this.el_.removeChild(r[e-1]);r.length=i.length})}}g.registerComponent("LoadProgressBar",rr);class nr extends g{constructor(e,t){super(e,t),this.update=vt(p(this,this.update),30)}createEl(){return super.createEl("div",{className:"vjs-time-tooltip"},{"aria-hidden":"true"})}update(s,r,n){var a=Ve(this.el_),o=je(this.player_.el()),r=s.width*r;if(o&&a){let e=s.left-o.left+r,t=s.width-r+(o.right-s.right),i=(t||(t=s.width-r,e=r),a.width/2);ea.width&&(i=a.width),i=Math.round(i),this.el_.style.right=`-${i}px`,this.write(n)}}write(e){xe(this.el_,e)}updateTime(r,n,a,o){this.requestNamedAnimationFrame("TimeTooltip#updateTime",()=>{let e;var t,i,s=this.player_.duration();e=this.player_.liveTracker&&this.player_.liveTracker.isLive()?((i=(t=this.player_.liveTracker.liveWindow())-n*t)<1?"":"-")+Wt(i,t):Wt(a,s),this.update(r,n,e),o&&o()})}}g.registerComponent("TimeTooltip",nr);class ar extends g{constructor(e,t){super(e,t),this.setIcon("circle"),this.update=vt(p(this,this.update),30)}createEl(){return super.createEl("div",{className:"vjs-play-progress vjs-slider-bar"},{"aria-hidden":"true"})}update(e,t,i){var s=this.getChild("timeTooltip");s&&(i=i&&i.target&&"function"==typeof i.target.pendingSeekTime?i.target.pendingSeekTime():this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime(),s.updateTime(e,t,i))}}ar.prototype.options_={children:[]},u||se||ar.prototype.options_.children.push("timeTooltip"),g.registerComponent("PlayProgressBar",ar);class or extends g{constructor(e,t){super(e,t),this.update=vt(p(this,this.update),30)}createEl(){return super.createEl("div",{className:"vjs-mouse-display"})}update(e,t){var i=t*this.player_.duration();this.getChild("timeTooltip").updateTime(e,t,i,()=>{this.el_.style.left=e.width*t+"px"})}}or.prototype.options_={children:["timeTooltip"]},g.registerComponent("MouseTimeDisplay",or);class lr extends ir{constructor(e,t){(t=d(lr.prototype.options_,t)).children=[...t.children];var i=e.options_.disableSeekWhileScrubbingOnMobile&&(u||se)||e.options_.disableSeekWhileScrubbingOnSTV;(u||se)&&!i||t.children.splice(1,0,"mouseTimeDisplay"),super(e,t),this.shouldDisableSeekWhileScrubbing_=i,this.pendingSeekTime_=null,this.setEventHandlers_()}setEventHandlers_(){this.update_=p(this,this.update),this.update=vt(this.update_,30),this.on(this.player_,["durationchange","timeupdate"],this.update),this.on(this.player_,["ended"],this.update_),this.player_.liveTracker&&this.on(this.player_.liveTracker,"liveedgechange",this.update),this.updateInterval=null,this.enableIntervalHandler_=e=>this.enableInterval_(e),this.disableIntervalHandler_=e=>this.disableInterval_(e),this.on(this.player_,["playing"],this.enableIntervalHandler_),this.on(this.player_,["ended","pause","waiting"],this.disableIntervalHandler_),"hidden"in document&&"visibilityState"in document&&this.on(document,"visibilitychange",this.toggleVisibility_)}toggleVisibility_(e){"hidden"===document.visibilityState?(this.cancelNamedAnimationFrame("SeekBar#update"),this.cancelNamedAnimationFrame("Slider#update"),this.disableInterval_(e)):(this.player_.ended()||this.player_.paused()||this.enableInterval_(),this.update())}enableInterval_(){this.updateInterval||(this.updateInterval=this.setInterval(this.update,30))}disableInterval_(e){this.player_.liveTracker&&this.player_.liveTracker.isLive()&&e&&"ended"!==e.type||this.updateInterval&&(this.clearInterval(this.updateInterval),this.updateInterval=null)}createEl(){return super.createEl("div",{className:"vjs-progress-holder"},{"aria-label":this.localize("Progress Bar")})}update(r){if("hidden"!==document.visibilityState){let s=super.update();return this.requestNamedAnimationFrame("SeekBar#update",()=>{var e=this.player_.ended()?this.player_.duration():this.getCurrentTime_(),t=this.player_.liveTracker;let i=this.player_.duration();t&&t.isLive()&&(i=this.player_.liveTracker.liveCurrentTime()),this.percent_!==s&&(this.el_.setAttribute("aria-valuenow",(100*s).toFixed(2)),this.percent_=s),this.currentTime_===e&&this.duration_===i||(this.el_.setAttribute("aria-valuetext",this.localize("progress bar timing: currentTime={1} duration={2}",[Wt(e,i),Wt(i,i)],"{1} of {2}")),this.currentTime_=e,this.duration_=i),this.bar&&this.bar.update(je(this.el()),this.getProgress(),r)}),s}}userSeek_(e){this.player_.liveTracker&&this.player_.liveTracker.isLive()&&this.player_.liveTracker.nextSeekedFromUser(),this.player_.currentTime(e)}getCurrentTime_(){return this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime()}pendingSeekTime(e){var t;return void 0!==e&&(null!==e?(t=this.player_.duration(),this.pendingSeekTime_=Math.max(0,Math.min(e,t))):this.pendingSeekTime_=null),this.pendingSeekTime_}getPercent(){if(null!==this.pendingSeekTime())return this.pendingSeekTime()/this.player_.duration();var e=this.getCurrentTime_();let t;var i=this.player_.liveTracker;return i&&i.isLive()?(t=(e-i.seekableStart())/i.liveWindow(),i.atLiveEdge()&&(t=1)):t=e/this.player_.duration(),t}handleMouseDown(e){Ke(e)&&(e.stopPropagation(),this.videoWasPlaying=!this.player_.paused(),this.shouldDisableSeekWhileScrubbing_||this.player_.pause(),super.handleMouseDown(e))}handleMouseMove(t,i=!1){if(Ke(t)&&!isNaN(this.player_.duration())){i||this.player_.scrubbing()||this.player_.scrubbing(!0);let e;i=this.calculateDistance(t),t=this.player_.liveTracker;if(t&&t.isLive()){if(.99<=i)return void t.seekToLiveEdge();var s=t.seekableStart(),r=t.liveCurrentTime();if((e=(e=(e=s+i*t.liveWindow())>=r?r:e)<=s?s+.1:e)===1/0)return}else(e=i*this.player_.duration())===this.player_.duration()&&(e-=.1);this.shouldDisableSeekWhileScrubbing_?this.pendingSeekTime(e):this.userSeek_(e),this.player_.options_.enableSmoothSeeking&&this.update()}}enable(){super.enable();var e=this.getChild("mouseTimeDisplay");e&&e.show()}disable(){super.disable();var e=this.getChild("mouseTimeDisplay");e&&e.hide()}handleMouseUp(e){super.handleMouseUp(e),e&&e.stopPropagation(),this.player_.scrubbing(!1),null!==this.pendingSeekTime()&&(this.userSeek_(this.pendingSeekTime()),this.pendingSeekTime(null)),this.player_.trigger({type:"timeupdate",target:this,manuallyTriggered:!0}),this.videoWasPlaying?Kt(this.player_.play()):this.update_()}handlePendingSeek_(e){this.player_.paused()||this.player_.pause();var t=null!==this.pendingSeekTime()?this.pendingSeekTime():this.player_.currentTime();this.pendingSeekTime(t+e),this.player_.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})}stepForward(){this.shouldDisableSeekWhileScrubbing_?this.handlePendingSeek_(this.options().stepSeconds):this.userSeek_(this.player_.currentTime()+this.options().stepSeconds)}stepBack(){this.shouldDisableSeekWhileScrubbing_?this.handlePendingSeek_(-this.options().stepSeconds):this.userSeek_(this.player_.currentTime()-this.options().stepSeconds)}handleAction(e){null!==this.pendingSeekTime()&&(this.userSeek_(this.pendingSeekTime()),this.pendingSeekTime(null)),this.player_.paused()?this.player_.play():this.player_.pause()}handleKeyDown(e){var t,i=this.player_.liveTracker;" "===e.key||"Enter"===e.key?(e.preventDefault(),e.stopPropagation(),this.handleAction(e)):"Home"===e.key?(e.preventDefault(),e.stopPropagation(),this.userSeek_(0)):"End"===e.key?(e.preventDefault(),e.stopPropagation(),i&&i.isLive()?this.userSeek_(i.liveCurrentTime()):this.userSeek_(this.player_.duration())):/^[0-9]$/.test(e.key)?(e.preventDefault(),e.stopPropagation(),t=.1*parseInt(e.key,10),i&&i.isLive()?this.userSeek_(i.seekableStart()+i.liveWindow()*t):this.userSeek_(this.player_.duration()*t)):"PageDown"===e.key?(e.preventDefault(),e.stopPropagation(),this.userSeek_(this.player_.currentTime()-this.options().stepSeconds*this.options().pageMultiplier)):"PageUp"===e.key?(e.preventDefault(),e.stopPropagation(),this.userSeek_(this.player_.currentTime()+this.options().stepSeconds*this.options().pageMultiplier)):super.handleKeyDown(e)}dispose(){this.disableInterval_(),this.off(this.player_,["durationchange","timeupdate"],this.update),this.off(this.player_,["ended"],this.update_),this.player_.liveTracker&&this.off(this.player_.liveTracker,"liveedgechange",this.update),this.off(this.player_,["playing"],this.enableIntervalHandler_),this.off(this.player_,["ended","pause","waiting"],this.disableIntervalHandler_),"hidden"in document&&"visibilityState"in document&&this.off(document,"visibilitychange",this.toggleVisibility_),super.dispose()}}lr.prototype.options_={children:["loadProgressBar","playProgressBar"],barName:"playProgressBar",stepSeconds:5,pageMultiplier:12},g.registerComponent("SeekBar",lr);class dr extends g{constructor(e,t){super(e,t),this.handleMouseMove=vt(p(this,this.handleMouseMove),30),this.throttledHandleMouseSeek=vt(p(this,this.handleMouseSeek),30),this.handleMouseUpHandler_=e=>this.handleMouseUp(e),this.handleMouseDownHandler_=e=>this.handleMouseDown(e),this.enable()}createEl(){return super.createEl("div",{className:"vjs-progress-control vjs-control"})}handleMouseMove(e){var t,i,s,r,n=this.getChild("seekBar");n&&(t=n.getChild("playProgressBar"),i=n.getChild("mouseTimeDisplay"),t||i)&&(s=Ve(r=n.el()),r=tr(r=He(r,e).x,0,1),i&&i.update(s,r),t)&&t.update(s,n.getProgress())}handleMouseSeek(e){var t=this.getChild("seekBar");t&&t.handleMouseMove(e)}enabled(){return this.enabled_}disable(){var e;this.children().forEach(e=>e.disable&&e.disable()),this.enabled()&&(this.off(["mousedown","touchstart"],this.handleMouseDownHandler_),this.off(this.el_,["mousemove","touchmove"],this.handleMouseMove),this.removeListenersAddedOnMousedownAndTouchstart(),this.addClass("disabled"),this.enabled_=!1,this.player_.scrubbing())&&(e=this.getChild("seekBar"),this.player_.scrubbing(!1),e.videoWasPlaying)&&Kt(this.player_.play())}enable(){this.children().forEach(e=>e.enable&&e.enable()),this.enabled()||(this.on(["mousedown","touchstart"],this.handleMouseDownHandler_),this.on(this.el_,["mousemove","touchmove"],this.handleMouseMove),this.removeClass("disabled"),this.enabled_=!0)}removeListenersAddedOnMousedownAndTouchstart(){var e=this.el_.ownerDocument;this.off(e,"mousemove",this.throttledHandleMouseSeek),this.off(e,"touchmove",this.throttledHandleMouseSeek),this.off(e,"mouseup",this.handleMouseUpHandler_),this.off(e,"touchend",this.handleMouseUpHandler_)}handleMouseDown(e){var t=this.el_.ownerDocument,i=this.getChild("seekBar");i&&i.handleMouseDown(e),this.on(t,"mousemove",this.throttledHandleMouseSeek),this.on(t,"touchmove",this.throttledHandleMouseSeek),this.on(t,"mouseup",this.handleMouseUpHandler_),this.on(t,"touchend",this.handleMouseUpHandler_)}handleMouseUp(e){var t=this.getChild("seekBar");t&&t.handleMouseUp(e),this.removeListenersAddedOnMousedownAndTouchstart()}}dr.prototype.options_={children:["seekBar"]},g.registerComponent("ProgressControl",dr);class hr extends s{constructor(e,t){super(e,t),this.setIcon("picture-in-picture-enter"),this.on(e,["enterpictureinpicture","leavepictureinpicture"],e=>this.handlePictureInPictureChange(e)),this.on(e,["disablepictureinpicturechanged","loadedmetadata"],e=>this.handlePictureInPictureEnabledChange(e)),this.on(e,["loadedmetadata","audioonlymodechange","audiopostermodechange"],()=>this.handlePictureInPictureAudioModeChange()),this.disable()}buildCSSClass(){return"vjs-picture-in-picture-control vjs-hidden "+super.buildCSSClass()}handlePictureInPictureAudioModeChange(){"audio"===this.player_.currentType().substring(0,5)||this.player_.audioPosterMode()||this.player_.audioOnlyMode()?(this.player_.isInPictureInPicture()&&this.player_.exitPictureInPicture(),this.hide()):this.show()}handlePictureInPictureEnabledChange(){document.pictureInPictureEnabled&&!1===this.player_.disablePictureInPicture()||this.player_.options_.enableDocumentPictureInPicture&&"documentPictureInPicture"in window?this.enable():this.disable()}handlePictureInPictureChange(e){this.player_.isInPictureInPicture()?(this.setIcon("picture-in-picture-exit"),this.controlText("Exit Picture-in-Picture")):(this.setIcon("picture-in-picture-enter"),this.controlText("Picture-in-Picture")),this.handlePictureInPictureEnabledChange()}handleClick(e){this.player_.isInPictureInPicture()?this.player_.exitPictureInPicture():this.player_.requestPictureInPicture()}show(){"function"==typeof document.exitPictureInPicture&&super.show()}}hr.prototype.controlText_="Picture-in-Picture",g.registerComponent("PictureInPictureToggle",hr);class ur extends s{constructor(e,t){super(e,t),this.setIcon("fullscreen-enter"),this.on(e,"fullscreenchange",e=>this.handleFullscreenChange(e)),!1===document[e.fsApi_.fullscreenEnabled]&&this.disable()}buildCSSClass(){return"vjs-fullscreen-control "+super.buildCSSClass()}handleFullscreenChange(e){this.player_.isFullscreen()?(this.controlText("Exit Fullscreen"),this.setIcon("fullscreen-exit")):(this.controlText("Fullscreen"),this.setIcon("fullscreen-enter"))}handleClick(e){this.player_.isFullscreen()?this.player_.exitFullscreen():this.player_.requestFullscreen()}}ur.prototype.controlText_="Fullscreen",g.registerComponent("FullscreenToggle",ur);class cr extends g{createEl(){var e=super.createEl("div",{className:"vjs-volume-level"});return this.setIcon("circle",e),e.appendChild(super.createEl("span",{className:"vjs-control-text"})),e}}g.registerComponent("VolumeLevel",cr);class pr extends g{constructor(e,t){super(e,t),this.update=vt(p(this,this.update),30)}createEl(){return super.createEl("div",{className:"vjs-volume-tooltip"},{"aria-hidden":"true"})}update(t,i,s,e){if(!s){var s=je(this.el_),r=je(this.player_.el()),i=t.width*i;if(!r||!s)return;var n=t.left-r.left+i,i=t.width-i+(r.right-t.right);let e=s.width/2;ns.width&&(e=s.width),this.el_.style.right=`-${e}px`}this.write(e+"%")}write(e){xe(this.el_,e)}updateVolume(e,t,i,s,r){this.requestNamedAnimationFrame("VolumeLevelTooltip#updateVolume",()=>{this.update(e,t,i,s.toFixed(0)),r&&r()})}}g.registerComponent("VolumeLevelTooltip",pr);class mr extends g{constructor(e,t){super(e,t),this.update=vt(p(this,this.update),30)}createEl(){return super.createEl("div",{className:"vjs-mouse-display"})}update(e,t,i){var s=100*t;this.getChild("volumeLevelTooltip").updateVolume(e,t,i,s,()=>{i?this.el_.style.bottom=e.height*t+"px":this.el_.style.left=e.width*t+"px"})}}mr.prototype.options_={children:["volumeLevelTooltip"]},g.registerComponent("MouseVolumeLevelDisplay",mr);class gr extends ir{constructor(e,t){super(e,t),this.on("slideractive",e=>this.updateLastVolume_(e)),this.on(e,"volumechange",e=>this.updateARIAAttributes(e)),e.ready(()=>this.updateARIAAttributes())}createEl(){return super.createEl("div",{className:"vjs-volume-bar vjs-slider-bar"},{"aria-label":this.localize("Volume Level"),"aria-live":"polite"})}handleMouseDown(e){Ke(e)&&super.handleMouseDown(e)}handleMouseMove(e){var t,i,s,r=this.getChild("mouseVolumeLevelDisplay");r&&(t=je(s=this.el()),i=this.vertical(),s=He(s,e),s=tr(s=i?s.y:s.x,0,1),r.update(t,s,i)),Ke(e)&&(this.checkMuted(),this.player_.volume(this.calculateDistance(e)))}checkMuted(){this.player_.muted()&&this.player_.muted(!1)}getPercent(){return this.player_.muted()?0:this.player_.volume()}stepForward(){this.checkMuted(),this.player_.volume(this.player_.volume()+.1)}stepBack(){this.checkMuted(),this.player_.volume(this.player_.volume()-.1)}updateARIAAttributes(e){var t=this.player_.muted()?0:this.volumeAsPercentage_();this.el_.setAttribute("aria-valuenow",t),this.el_.setAttribute("aria-valuetext",t+"%")}volumeAsPercentage_(){return Math.round(100*this.player_.volume())}updateLastVolume_(){let e=this.player_.volume();this.one("sliderinactive",()=>{0===this.player_.volume()&&this.player_.lastVolume_(e)})}}gr.prototype.options_={children:["volumeLevel"],barName:"volumeLevel"},u||se||gr.prototype.options_.children.splice(0,0,"mouseVolumeLevelDisplay"),gr.prototype.playerEvent="volumechange",g.registerComponent("VolumeBar",gr);class fr extends g{constructor(e,t={}){var i,s;t.vertical=t.vertical||!1,"undefined"!=typeof t.volumeBar&&!Q(t.volumeBar)||(t.volumeBar=t.volumeBar||{},t.volumeBar.vertical=t.vertical),super(e,t),i=this,(s=e).tech_&&!s.tech_.featuresVolumeControl&&i.addClass("vjs-hidden"),i.on(s,"loadstart",function(){s.tech_.featuresVolumeControl?i.removeClass("vjs-hidden"):i.addClass("vjs-hidden")}),this.throttledHandleMouseMove=vt(p(this,this.handleMouseMove),30),this.handleMouseUpHandler_=e=>this.handleMouseUp(e),this.on("mousedown",e=>this.handleMouseDown(e)),this.on("touchstart",e=>this.handleMouseDown(e)),this.on("mousemove",e=>this.handleMouseMove(e)),this.on(this.volumeBar,["focus","slideractive"],()=>{this.volumeBar.addClass("vjs-slider-active"),this.addClass("vjs-slider-active"),this.trigger("slideractive")}),this.on(this.volumeBar,["blur","sliderinactive"],()=>{this.volumeBar.removeClass("vjs-slider-active"),this.removeClass("vjs-slider-active"),this.trigger("sliderinactive")})}createEl(){let e="vjs-volume-horizontal";return this.options_.vertical&&(e="vjs-volume-vertical"),super.createEl("div",{className:"vjs-volume-control vjs-control "+e})}handleMouseDown(e){var t=this.el_.ownerDocument;this.on(t,"mousemove",this.throttledHandleMouseMove),this.on(t,"touchmove",this.throttledHandleMouseMove),this.on(t,"mouseup",this.handleMouseUpHandler_),this.on(t,"touchend",this.handleMouseUpHandler_)}handleMouseUp(e){var t=this.el_.ownerDocument;this.off(t,"mousemove",this.throttledHandleMouseMove),this.off(t,"touchmove",this.throttledHandleMouseMove),this.off(t,"mouseup",this.handleMouseUpHandler_),this.off(t,"touchend",this.handleMouseUpHandler_)}handleMouseMove(e){this.volumeBar.handleMouseMove(e)}}fr.prototype.options_={children:["volumeBar"]},g.registerComponent("VolumeControl",fr);class yr extends s{constructor(e,t){var i,s;super(e,t),i=this,(s=e).tech_&&!s.tech_.featuresMuteControl&&i.addClass("vjs-hidden"),i.on(s,"loadstart",function(){s.tech_.featuresMuteControl?i.removeClass("vjs-hidden"):i.addClass("vjs-hidden")}),this.on(e,["loadstart","volumechange"],e=>this.update(e))}buildCSSClass(){return"vjs-mute-control "+super.buildCSSClass()}handleClick(e){var t=this.player_.volume(),i=this.player_.lastVolume_();0===t?(this.player_.volume(i<.1?.1:i),this.player_.muted(!1)):this.player_.muted(!this.player_.muted())}update(e){this.updateIcon_(),this.updateControlText_()}updateIcon_(){var e=this.player_.volume();let t=3;this.setIcon("volume-high"),u&&this.player_.tech_&&this.player_.tech_.el_&&this.player_.muted(this.player_.tech_.el_.muted),0===e||this.player_.muted()?(this.setIcon("volume-mute"),t=0):e<.33?(this.setIcon("volume-low"),t=1):e<.67&&(this.setIcon("volume-medium"),t=2),Le(this.el_,[0,1,2,3].reduce((e,t)=>e+`${t?" ":""}vjs-vol-`+t,"")),Pe(this.el_,"vjs-vol-"+t)}updateControlText_(){var e=this.player_.muted()||0===this.player_.volume()?"Unmute":"Mute";this.controlText()!==e&&this.controlText(e)}}yr.prototype.controlText_="Mute",g.registerComponent("MuteToggle",yr);class _r extends g{constructor(e,t={}){"undefined"!=typeof t.inline?t.inline=t.inline:t.inline=!0,"undefined"!=typeof t.volumeControl&&!Q(t.volumeControl)||(t.volumeControl=t.volumeControl||{},t.volumeControl.vertical=!t.inline),super(e,t),this.handleKeyPressHandler_=e=>this.handleKeyPress(e),this.on(e,["loadstart"],e=>this.volumePanelState_(e)),this.on(this.muteToggle,"keyup",e=>this.handleKeyPress(e)),this.on(this.volumeControl,"keyup",e=>this.handleVolumeControlKeyUp(e)),this.on("keydown",e=>this.handleKeyPress(e)),this.on("mouseover",e=>this.handleMouseOver(e)),this.on("mouseout",e=>this.handleMouseOut(e)),this.on(this.volumeControl,["slideractive"],this.sliderActive_),this.on(this.volumeControl,["sliderinactive"],this.sliderInactive_)}sliderActive_(){this.addClass("vjs-slider-active")}sliderInactive_(){this.removeClass("vjs-slider-active")}volumePanelState_(){this.volumeControl.hasClass("vjs-hidden")&&this.muteToggle.hasClass("vjs-hidden")&&this.addClass("vjs-hidden"),this.volumeControl.hasClass("vjs-hidden")&&!this.muteToggle.hasClass("vjs-hidden")&&this.addClass("vjs-mute-toggle-only")}createEl(){let e="vjs-volume-panel-horizontal";return this.options_.inline||(e="vjs-volume-panel-vertical"),super.createEl("div",{className:"vjs-volume-panel vjs-control "+e})}dispose(){this.handleMouseOut(),super.dispose()}handleVolumeControlKeyUp(e){"Escape"===e.key&&this.muteToggle.focus()}handleMouseOver(e){this.addClass("vjs-hover"),mt(document,"keyup",this.handleKeyPressHandler_)}handleMouseOut(e){this.removeClass("vjs-hover"),c(document,"keyup",this.handleKeyPressHandler_)}handleKeyPress(e){"Escape"===e.key&&this.handleMouseOut()}}_r.prototype.options_={children:["muteToggle","volumeControl"]},g.registerComponent("VolumePanel",_r);class vr extends s{constructor(e,t){super(e,t),this.validOptions=[5,10,30],this.skipTime=this.getSkipForwardTime(),this.skipTime&&this.validOptions.includes(this.skipTime)?(this.setIcon("forward-"+this.skipTime),this.controlText(this.localize("Skip forward {1} seconds",[this.skipTime.toLocaleString(e.language())])),this.show()):this.hide()}getSkipForwardTime(){var e=this.options_.playerOptions;return e.controlBar&&e.controlBar.skipButtons&&e.controlBar.skipButtons.forward}buildCSSClass(){return`vjs-skip-forward-${this.getSkipForwardTime()} `+super.buildCSSClass()}handleClick(e){if(!isNaN(this.player_.duration())){var t=this.player_.currentTime(),i=this.player_.liveTracker,i=i&&i.isLive()?i.seekableEnd():this.player_.duration();let e;e=t+this.skipTime<=i?t+this.skipTime:i,this.player_.currentTime(e)}}handleLanguagechange(){this.controlText(this.localize("Skip forward {1} seconds",[this.skipTime]))}}vr.prototype.controlText_="Skip Forward",g.registerComponent("SkipForward",vr);class br extends s{constructor(e,t){super(e,t),this.validOptions=[5,10,30],this.skipTime=this.getSkipBackwardTime(),this.skipTime&&this.validOptions.includes(this.skipTime)?(this.setIcon("replay-"+this.skipTime),this.controlText(this.localize("Skip backward {1} seconds",[this.skipTime.toLocaleString(e.language())])),this.show()):this.hide()}getSkipBackwardTime(){var e=this.options_.playerOptions;return e.controlBar&&e.controlBar.skipButtons&&e.controlBar.skipButtons.backward}buildCSSClass(){return`vjs-skip-backward-${this.getSkipBackwardTime()} `+super.buildCSSClass()}handleClick(e){var t=this.player_.currentTime(),i=this.player_.liveTracker,i=i&&i.isLive()&&i.seekableStart();let s;s=i&&t-this.skipTime<=i?i:t>=this.skipTime?t-this.skipTime:0,this.player_.currentTime(s)}handleLanguagechange(){this.controlText(this.localize("Skip backward {1} seconds",[this.skipTime]))}}br.prototype.controlText_="Skip Backward",g.registerComponent("SkipBackward",br);class Tr extends g{constructor(e,t){super(e,t),t&&(this.menuButton_=t.menuButton),this.focusedChild_=-1,this.on("keydown",e=>this.handleKeyDown(e)),this.boundHandleBlur_=e=>this.handleBlur(e),this.boundHandleTapClick_=e=>this.handleTapClick(e)}addEventListenerForItem(e){e instanceof g&&(this.on(e,"blur",this.boundHandleBlur_),this.on(e,["tap","click"],this.boundHandleTapClick_))}removeEventListenerForItem(e){e instanceof g&&(this.off(e,"blur",this.boundHandleBlur_),this.off(e,["tap","click"],this.boundHandleTapClick_))}removeChild(e){"string"==typeof e&&(e=this.getChild(e)),this.removeEventListenerForItem(e),super.removeChild(e)}addItem(e){e=this.addChild(e);e&&this.addEventListenerForItem(e)}createEl(){var e=this.options_.contentElType||"ul",e=(this.contentEl_=l(e,{className:"vjs-menu-content"}),this.contentEl_.setAttribute("role","menu"),super.createEl("div",{append:this.contentEl_,className:"vjs-menu"}));return e.appendChild(this.contentEl_),mt(e,"click",function(e){e.preventDefault(),e.stopImmediatePropagation()}),e}dispose(){this.contentEl_=null,this.boundHandleBlur_=null,this.boundHandleTapClick_=null,super.dispose()}handleBlur(e){let t=e.relatedTarget||document.activeElement;this.children().some(e=>e.el()===t)||(e=this.menuButton_)&&e.buttonPressed_&&t!==e.el().firstChild&&e.unpressButton()}handleTapClick(t){var e;this.menuButton_&&(this.menuButton_.unpressButton(),e=this.children(),Array.isArray(e))&&(e=e.filter(e=>e.el()===t.target)[0])&&"CaptionSettingsMenuItem"!==e.name()&&this.menuButton_.focus()}handleKeyDown(e){"ArrowLeft"===e.key||"ArrowDown"===e.key?(e.preventDefault(),e.stopPropagation(),this.stepForward()):"ArrowRight"!==e.key&&"ArrowUp"!==e.key||(e.preventDefault(),e.stopPropagation(),this.stepBack())}stepForward(){let e=0;void 0!==this.focusedChild_&&(e=this.focusedChild_+1),this.focus(e)}stepBack(){let e=0;void 0!==this.focusedChild_&&(e=this.focusedChild_-1),this.focus(e)}focus(e=0){var t=this.children().slice();t.length&&t[0].hasClass("vjs-menu-title")&&t.shift(),0this.handleClick(e);this.handleMenuKeyUp_=e=>this.handleMenuKeyUp(e),this.on(this.menuButton_,"tap",t),this.on(this.menuButton_,"click",t),this.on(this.menuButton_,"keydown",e=>this.handleKeyDown(e)),this.on(this.menuButton_,"mouseenter",()=>{this.addClass("vjs-hover"),this.menu.show(),mt(document,"keyup",this.handleMenuKeyUp_)}),this.on("mouseleave",e=>this.handleMouseLeave(e)),this.on("keydown",e=>this.handleSubmenuKeyDown(e))}update(){var e=this.createMenu();this.menu&&(this.menu.dispose(),this.removeChild(this.menu)),this.menu=e,this.addChild(e),this.buttonPressed_=!1,this.menuButton_.el_.setAttribute("aria-expanded","false"),this.items&&this.items.length<=this.hideThreshold_?(this.hide(),this.menu.contentEl_.removeAttribute("role")):(this.show(),this.menu.contentEl_.setAttribute("role","menu"))}createMenu(){var e,t=new Tr(this.player_,{menuButton:this});if(this.hideThreshold_=0,this.options_.title&&(e=l("li",{className:"vjs-menu-title",textContent:m(this.options_.title),tabIndex:-1}),e=new g(this.player_,{el:e}),t.addItem(e)),this.items=this.createItems(),this.items)for(let e=0;e{this.handleTracksChange.apply(this,e)}),n=(...e)=>{this.handleSelectedLanguageChange.apply(this,e)};if(e.on(["loadstart","texttrackchange"],r),s.addEventListener("change",r),s.addEventListener("selectedlanguagechange",n),this.on("dispose",function(){e.off(["loadstart","texttrackchange"],r),s.removeEventListener("change",r),s.removeEventListener("selectedlanguagechange",n)}),void 0===s.onchange){let e;this.on(["tap","click"],function(){if("object"!=typeof window.Event)try{e=new window.Event("change")}catch(e){}e||(e=document.createEvent("Event")).initEvent("change",!0,!0),s.dispatchEvent(e)})}this.handleTracksChange()}handleClick(e){var t=this.track,i=this.player_.textTracks();if(super.handleClick(e),i)for(let e=0;e{this.items.forEach(e=>{e.selected(this.track_.activeCues[0]===e.cue)})}}buildCSSClass(){return"vjs-chapters-button "+super.buildCSSClass()}buildWrapperCSSClass(){return"vjs-chapters-button "+super.buildWrapperCSSClass()}update(e){e&&e.track&&"chapters"!==e.track.kind||((e=this.findChaptersTrack())!==this.track_?(this.setTrack(e),super.update()):(!this.items||e&&e.cues&&e.cues.length!==this.items.length)&&super.update())}setTrack(e){var t;this.track_!==e&&(this.updateHandler_||(this.updateHandler_=this.update.bind(this)),this.track_&&((t=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_))&&t.removeEventListener("load",this.updateHandler_),this.track_.removeEventListener("cuechange",this.selectCurrentItem_),this.track_=null),this.track_=e,this.track_)&&(this.track_.mode="hidden",(t=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_))&&t.addEventListener("load",this.updateHandler_),this.track_.addEventListener("cuechange",this.selectCurrentItem_))}findChaptersTrack(){var t=this.player_.textTracks()||[];for(let e=t.length-1;0<=e;e--){var i=t[e];if(i.kind===this.kind_)return i}}getMenuCaption(){return this.track_&&this.track_.label?this.track_.label:this.localize(m(this.kind_))}createMenu(){return this.options_.title=this.getMenuCaption(),super.createMenu()}createItems(){var i=[];if(this.track_){var s=this.track_.cues;if(s)for(let e=0,t=s.length;e{this.handleTracksChange.apply(this,e)});s.addEventListener("change",r),this.on("dispose",()=>{s.removeEventListener("change",r)})}createEl(e,t,i){e=super.createEl(e,t,i),t=e.querySelector(".vjs-menu-item-text");return 0<=["main-desc","descriptions"].indexOf(this.options_.track.kind)&&(t.appendChild(l("span",{className:"vjs-icon-placeholder"},{"aria-hidden":!0})),t.appendChild(l("span",{className:"vjs-control-text",textContent:" "+this.localize("Descriptions")}))),e}handleClick(e){if(super.handleClick(e),this.track.enabled=!0,this.player_.tech_.featuresNativeAudioTracks){var t=this.player_.audioTracks();for(let e=0;ethis.update(e))}handleClick(e){super.handleClick(),this.player().playbackRate(this.rate)}update(e){this.selected(this.player().playbackRate()===this.rate)}}Br.prototype.contentElType="button",g.registerComponent("PlaybackRateMenuItem",Br);class Fr extends Sr{constructor(e,t){super(e,t),this.menuButton_.el_.setAttribute("aria-describedby",this.labelElId_),this.updateVisibility(),this.updateLabel(),this.on(e,"loadstart",e=>this.updateVisibility(e)),this.on(e,"ratechange",e=>this.updateLabel(e)),this.on(e,"playbackrateschange",e=>this.handlePlaybackRateschange(e))}createEl(){var e=super.createEl();return this.labelElId_="vjs-playback-rate-value-label-"+this.id_,this.labelEl_=l("div",{className:"vjs-playback-rate-value",id:this.labelElId_,textContent:"1x"}),e.appendChild(this.labelEl_),e}dispose(){this.labelEl_=null,super.dispose()}buildCSSClass(){return"vjs-playback-rate "+super.buildCSSClass()}buildWrapperCSSClass(){return"vjs-playback-rate "+super.buildWrapperCSSClass()}createItems(){var t=this.playbackRates(),i=[];for(let e=t.length-1;0<=e;e--)i.push(new Br(this.player(),{rate:t[e]+"x"}));return i}handlePlaybackRateschange(e){this.update()}playbackRates(){var e=this.player();return e.playbackRates&&e.playbackRates()||[]}playbackRateSupported(){return this.player().tech_&&this.player().tech_.featuresPlaybackRate&&this.playbackRates()&&0{this.open(e)})}buildCSSClass(){return"vjs-error-display "+super.buildCSSClass()}content(){var e=this.player().error();return e?this.localize(e.message):""}}Hr.prototype.options_=Object.assign({},ii.prototype.options_,{pauseOnOpen:!1,fillAlways:!0,temporary:!1,uncloseable:!0}),g.registerComponent("ErrorDisplay",Hr);class zr extends g{constructor(e,t={}){super(e,t),this.el_.setAttribute("aria-labelledby",this.selectLabelledbyIds)}createEl(){return this.selectLabelledbyIds=[this.options_.legendId,this.options_.labelId].join(" ").trim(),l("select",{id:this.options_.id},{},this.options_.SelectOptions.map(e=>{var t=(this.options_.labelId||"vjs-track-option-"+lt++)+"-"+e[1].replace(/\W+/g,""),e=l("option",{id:t,value:this.localize(e[0]),textContent:this.localize(e[1])});return e.setAttribute("aria-labelledby",this.selectLabelledbyIds+" "+t),e}))}}g.registerComponent("TextTrackSelect",zr);class $r extends g{constructor(t,e={}){super(t,e);var i,e=l("legend",{textContent:this.localize(this.options_.legendText),id:this.options_.legendId}),e=(this.el().appendChild(e),this.options_.selects);for(i of e){var s=this.options_.selectConfigs[i],r=s.className,n=s.id.replace("%s",this.options_.id_);let e=null;var a="vjs_select_"+lt++,r=("colors"===this.options_.type&&(e=l("span",{className:r}),(r=l("label",{id:n,className:"vjs-label",textContent:this.localize(s.label)})).setAttribute("for",a),e.appendChild(r)),new zr(t,{SelectOptions:s.options,legendId:this.options_.legendId,id:a,labelId:n}));this.addChild(r),"colors"===this.options_.type&&(e.appendChild(r.el()),this.el().appendChild(e))}}createEl(){return l("fieldset",{className:this.options_.className})}}g.registerComponent("TextTrackFieldset",$r);class Wr extends g{constructor(e,t={}){super(e,t);var t=this.options_.textTrackComponentid,i=new $r(e,{id_:t,legendId:"captions-text-legend-"+t,legendText:this.localize("Text"),className:"vjs-fg vjs-track-setting",selects:this.options_.fieldSets[0],selectConfigs:this.options_.selectConfigs,type:"colors"}),i=(this.addChild(i),new $r(e,{id_:t,legendId:"captions-background-"+t,legendText:this.localize("Text Background"),className:"vjs-bg vjs-track-setting",selects:this.options_.fieldSets[1],selectConfigs:this.options_.selectConfigs,type:"colors"})),i=(this.addChild(i),new $r(e,{id_:t,legendId:"captions-window-"+t,legendText:this.localize("Caption Area Background"),className:"vjs-window vjs-track-setting",selects:this.options_.fieldSets[2],selectConfigs:this.options_.selectConfigs,type:"colors"}));this.addChild(i)}createEl(){return l("div",{className:"vjs-track-settings-colors"})}}g.registerComponent("TextTrackSettingsColors",Wr);class Gr extends g{constructor(e,t={}){super(e,t);var t=this.options_.textTrackComponentid,i=new $r(e,{id_:t,legendId:"captions-font-size-"+t,legendText:"Font Size",className:"vjs-font-percent vjs-track-setting",selects:this.options_.fieldSets[0],selectConfigs:this.options_.selectConfigs,type:"font"}),i=(this.addChild(i),new $r(e,{id_:t,legendId:"captions-edge-style-"+t,legendText:this.localize("Text Edge Style"),className:"vjs-edge-style vjs-track-setting",selects:this.options_.fieldSets[1],selectConfigs:this.options_.selectConfigs,type:"font"})),i=(this.addChild(i),new $r(e,{id_:t,legendId:"captions-font-family-"+t,legendText:this.localize("Font Family"),className:"vjs-font-family vjs-track-setting",selects:this.options_.fieldSets[2],selectConfigs:this.options_.selectConfigs,type:"font"}));this.addChild(i)}createEl(){return l("div",{className:"vjs-track-settings-font"})}}g.registerComponent("TextTrackSettingsFont",Gr);class Xr extends g{constructor(e,t={}){super(e,t);t=new s(e,{controlText:this.localize("restore all settings to the default values"),className:"vjs-default-button"}),t.el().classList.remove("vjs-control","vjs-button"),t.el().textContent=this.localize("Reset"),this.addChild(t),t=this.localize("Done"),e=new s(e,{controlText:t,className:"vjs-done-button"});e.el().classList.remove("vjs-control","vjs-button"),e.el().textContent=t,this.addChild(e)}createEl(){return l("div",{className:"vjs-track-settings-controls"})}}g.registerComponent("TrackSettingsControls",Xr);let Kr="vjs-text-track-settings";var e=["#000","Black"],xi=["#00F","Blue"],Yr=["#0FF","Cyan"],Qr=["#0F0","Green"],r=["#F0F","Magenta"],Jr=["#F00","Red"],Zr=["#FFF","White"],n=["#FF0","Yellow"],en=["1","Opaque"],tn=["0.5","Semi-Transparent"],sn=["0","Transparent"];let rn={backgroundColor:{selector:".vjs-bg-color > select",id:"captions-background-color-%s",label:"Color",options:[e,Zr,Jr,Qr,xi,n,r,Yr],className:"vjs-bg-color"},backgroundOpacity:{selector:".vjs-bg-opacity > select",id:"captions-background-opacity-%s",label:"Opacity",options:[en,tn,sn],className:"vjs-bg-opacity vjs-opacity"},color:{selector:".vjs-text-color > select",id:"captions-foreground-color-%s",label:"Color",options:[Zr,e,Jr,Qr,xi,n,r,Yr],className:"vjs-text-color"},edgeStyle:{selector:".vjs-edge-style > select",id:"",label:"Text Edge Style",options:[["none","None"],["raised","Raised"],["depressed","Depressed"],["uniform","Uniform"],["dropshadow","Drop shadow"]]},fontFamily:{selector:".vjs-font-family > select",id:"",label:"Font Family",options:[["proportionalSansSerif","Proportional Sans-Serif"],["monospaceSansSerif","Monospace Sans-Serif"],["proportionalSerif","Proportional Serif"],["monospaceSerif","Monospace Serif"],["casual","Casual"],["script","Script"],["small-caps","Small Caps"]]},fontPercent:{selector:".vjs-font-percent > select",id:"",label:"Font Size",options:[["0.50","50%"],["0.75","75%"],["1.00","100%"],["1.25","125%"],["1.50","150%"],["1.75","175%"],["2.00","200%"],["3.00","300%"],["4.00","400%"]],default:2,parser:e=>"1.00"===e?null:Number(e)},textOpacity:{selector:".vjs-text-opacity > select",id:"captions-foreground-opacity-%s",label:"Opacity",options:[en,tn],className:"vjs-text-opacity vjs-opacity"},windowColor:{selector:".vjs-window-color > select",id:"captions-window-color-%s",label:"Color",className:"vjs-window-color"},windowOpacity:{selector:".vjs-window-opacity > select",id:"captions-window-opacity-%s",label:"Opacity",options:[sn,tn,en],className:"vjs-window-opacity vjs-opacity"}};function nn(e,t){if((e=t?t(e):e)&&"none"!==e)return e}rn.windowColor.options=rn.backgroundColor.options;class an extends ii{constructor(e,t){t.temporary=!1,super(e,t),this.updateDisplay=this.updateDisplay.bind(this),this.fill(),this.hasBeenOpened_=this.hasBeenFilled_=!0,this.renderModalComponents(e),this.endDialog=l("p",{className:"vjs-control-text",textContent:this.localize("End of dialog window.")}),this.el().appendChild(this.endDialog),this.setDefaults(),void 0===t.persistTextTrackSettings&&(this.options_.persistTextTrackSettings=this.options_.playerOptions.persistTextTrackSettings),this.bindFunctionsToSelectsAndButtons(),this.options_.persistTextTrackSettings&&this.restoreSettings()}renderModalComponents(e){var t=new Wr(e,{textTrackComponentid:this.id_,selectConfigs:rn,fieldSets:[["color","textOpacity"],["backgroundColor","backgroundOpacity"],["windowColor","windowOpacity"]]}),t=(this.addChild(t),new Gr(e,{textTrackComponentid:this.id_,selectConfigs:rn,fieldSets:[["fontPercent"],["edgeStyle"],["fontFamily"]]})),t=(this.addChild(t),new Xr(e));this.addChild(t)}bindFunctionsToSelectsAndButtons(){this.on(this.$(".vjs-done-button"),["click","tap"],()=>{this.saveSettings(),this.close()}),this.on(this.$(".vjs-default-button"),["click","tap"],()=>{this.setDefaults(),this.updateDisplay()}),X(rn,e=>{this.on(this.$(e.selector),"change",this.updateDisplay)})}dispose(){this.endDialog=null,super.dispose()}label(){return this.localize("Caption Settings Dialog")}description(){return this.localize("Beginning of dialog window. Escape will cancel and close the window.")}buildCSSClass(){return super.buildCSSClass()+" vjs-text-track-settings"}getValues(){return K(rn,(e,t,i)=>{s=this.$(t.selector),t=t.parser;var s=nn(s.options[s.options.selectedIndex].value,t);return void 0!==s&&(e[i]=s),e},{})}setValues(n){X(rn,(e,t)=>{var i=this.$(e.selector),s=n[t],r=e.parser;if(s)for(let e=0;e{var t=e.hasOwnProperty("default")?e.default:0;this.$(e.selector).selectedIndex=t})}restoreSettings(){let e;try{e=JSON.parse(window.localStorage.getItem(Kr))}catch(e){o.warn(e)}e&&this.setValues(e)}saveSettings(){if(this.options_.persistTextTrackSettings){var e=this.getValues();try{Object.keys(e).length?window.localStorage.setItem(Kr,JSON.stringify(e)):window.localStorage.removeItem(Kr)}catch(e){o.warn(e)}}}updateDisplay(){var e=this.player_.getChild("textTrackDisplay");e&&e.updateDisplay()}handleLanguagechange(){this.fill(),this.renderModalComponents(this.player_),this.bindFunctionsToSelectsAndButtons()}}g.registerComponent("TextTrackSettings",an);class on extends g{constructor(e,t){let i=t.ResizeObserver||window.ResizeObserver;super(e,d({createEl:!(i=null===t.ResizeObserver?!1:i),reportTouchActivity:!1},t)),this.ResizeObserver=t.ResizeObserver||window.ResizeObserver,this.loadListener_=null,this.resizeObserver_=null,this.debouncedHandler_=bt(()=>{this.resizeHandler()},100,!1,this),i?(this.resizeObserver_=new this.ResizeObserver(this.debouncedHandler_),this.resizeObserver_.observe(e.el())):(this.loadListener_=()=>{if(this.el_&&this.el_.contentWindow){let e=this.debouncedHandler_,t=this.unloadListener_=function(){c(this,"resize",e),c(this,"unload",t),t=null};mt(this.el_.contentWindow,"unload",t),mt(this.el_.contentWindow,"resize",e)}},this.one("load",this.loadListener_))}createEl(){return super.createEl("iframe",{className:"vjs-resize-manager",tabIndex:-1,title:this.localize("No content")},{"aria-hidden":"true"})}resizeHandler(){this.player_&&this.player_.trigger&&this.player_.trigger("playerresize")}dispose(){this.debouncedHandler_&&this.debouncedHandler_.cancel(),this.resizeObserver_&&(this.player_.el()&&this.resizeObserver_.unobserve(this.player_.el()),this.resizeObserver_.disconnect()),this.loadListener_&&this.off("load",this.loadListener_),this.el_&&this.el_.contentWindow&&this.unloadListener_&&this.unloadListener_.call(this.el_.contentWindow),this.ResizeObserver=null,this.resizeObserver=null,this.debouncedHandler_=null,this.loadListener_=null,super.dispose()}}g.registerComponent("ResizeManager",on);let ln={trackingThreshold:20,liveTolerance:15};class dn extends g{constructor(e,t){super(e,d(ln,t,{createEl:!1})),this.trackLiveHandler_=()=>this.trackLive_(),this.handlePlay_=e=>this.handlePlay(e),this.handleFirstTimeupdate_=e=>this.handleFirstTimeupdate(e),this.handleSeeked_=e=>this.handleSeeked(e),this.seekToLiveEdge_=e=>this.seekToLiveEdge(e),this.reset_(),this.on(this.player_,"durationchange",e=>this.handleDurationchange(e)),this.on(this.player_,"canplay",()=>this.toggleTracking())}trackLive_(){var t=this.player_.seekable();if(t&&t.length){var t=Number(window.performance.now().toFixed(4)),i=-1===this.lastTime_?0:(t-this.lastTime_)/1e3,t=(this.lastTime_=t,this.pastSeekEnd_=this.pastSeekEnd()+i,this.liveCurrentTime()),i=this.player_.currentTime();let e=this.player_.paused()||this.seekedBehindLive_||Math.abs(t-i)>this.options_.liveTolerance;(e=this.timeupdateSeen_&&t!==1/0?e:!1)!==this.behindLiveEdge_&&(this.behindLiveEdge_=e,this.trigger("liveedgechange"))}}handleDurationchange(){this.toggleTracking()}toggleTracking(){this.player_.duration()===1/0&&this.liveWindow()>=this.options_.trackingThreshold?(this.player_.options_.liveui&&this.player_.addClass("vjs-liveui"),this.startTracking()):(this.player_.removeClass("vjs-liveui"),this.stopTracking())}startTracking(){this.isTracking()||(this.timeupdateSeen_||(this.timeupdateSeen_=this.player_.hasStarted()),this.trackingInterval_=this.setInterval(this.trackLiveHandler_,30),this.trackLive_(),this.on(this.player_,["play","pause"],this.trackLiveHandler_),this.timeupdateSeen_?this.on(this.player_,"seeked",this.handleSeeked_):(this.one(this.player_,"play",this.handlePlay_),this.one(this.player_,"timeupdate",this.handleFirstTimeupdate_)))}handleFirstTimeupdate(){this.timeupdateSeen_=!0,this.on(this.player_,"seeked",this.handleSeeked_)}handleSeeked(){var e=Math.abs(this.liveCurrentTime()-this.player_.currentTime());this.seekedBehindLive_=this.nextSeekedFromUser_&&2this.updateDom_()),this.updateDom_()}createEl(){return this.els={title:l("div",{className:"vjs-title-bar-title",id:"vjs-title-bar-title-"+lt++}),description:l("div",{className:"vjs-title-bar-description",id:"vjs-title-bar-description-"+lt++})},l("div",{className:"vjs-title-bar"},{},J(this.els))}updateDom_(){var e=this.player_.tech_;let s=e&&e.el_,r={title:"aria-labelledby",description:"aria-describedby"};["title","description"].forEach(e=>{var t=this.state[e],i=this.els[e],e=r[e];$e(i),t&&xe(i,t),s&&(s.removeAttribute(e),t)&&s.setAttribute(e,i.id)}),this.state.title||this.state.description?this.show():this.hide()}update(e){this.setState(e)}dispose(){var e=this.player_.tech_,e=e&&e.el_;e&&(e.removeAttribute("aria-labelledby"),e.removeAttribute("aria-describedby")),super.dispose(),this.els=null}}g.registerComponent("TitleBar",hn);let un={initialDisplay:4e3,position:[],takeFocus:!1};class cn extends s{constructor(e,t){super(e,t=d(un,t)),this.controlText(t.controlText),this.hide(),this.on(this.player_,["useractive","userinactive"],e=>{this.removeClass("force-display")})}buildCSSClass(){return"vjs-transient-button focus-visible "+this.options_.position.map(e=>"vjs-"+e).join(" ")}createEl(){var e=l("button",{},{type:"button",class:this.buildCSSClass()},l("span"));return this.controlTextEl_=e.querySelector("span"),e}show(){super.show(),this.addClass("force-display"),this.options_.takeFocus&&this.el().focus({preventScroll:!0}),this.forceDisplayTimeout=this.player_.setTimeout(()=>{this.removeClass("force-display")},this.options_.initialDisplay)}hide(){this.removeClass("force-display"),super.hide()}dispose(){this.player_.clearTimeout(this.forceDisplayTimeout),super.dispose()}}g.registerComponent("TransientButton",cn);function pn(s){let r=s.el();if(!r.resetSourceWatch_){let t={},e=_n(s),i=t=>(...e)=>{e=t.apply(r,e);return gn(s),e};["append","appendChild","insertAdjacentHTML"].forEach(e=>{r[e]&&(t[e]=r[e],r[e]=i(t[e]))}),Object.defineProperty(r,"innerHTML",d(e,{set:i(e.set)})),r.resetSourceWatch_=()=>{r.resetSourceWatch_=null,Object.keys(t).forEach(e=>{r[e]=t[e]}),Object.defineProperty(r,"innerHTML",e)},s.one("sourceset",r.resetSourceWatch_)}}function mn(n){if(n.featuresSourceset){let r=n.el();if(!r.resetSourceset_){e=n;let t=yn([e.el(),window.HTMLMediaElement.prototype,vn],"src");var e;let i=r.setAttribute,s=r.load;Object.defineProperty(r,"src",d(t,{set:e=>{e=t.set.call(r,e);return n.triggerSourceset(r.src),e}})),r.setAttribute=(e,t)=>{t=i.call(r,e,t);return/src/i.test(e)&&n.triggerSourceset(r.src),t},r.load=()=>{var e=s.call(r);return gn(n)||(n.triggerSourceset(""),pn(n)),e},r.currentSrc?n.triggerSourceset(r.currentSrc):gn(n)||pn(n),r.resetSourceset_=()=>{r.resetSourceset_=null,r.load=s,r.setAttribute=i,Object.defineProperty(r,"src",t),r.resetSourceWatch_&&r.resetSourceWatch_()}}}}let gn=t=>{var e=t.el();if(e.hasAttribute("src"))t.triggerSourceset(e.src);else{var i=t.$$("source"),s=[];let e="";if(!i.length)return!1;for(let e=0;e{let s={};for(let e=0;eyn([e.el(),window.HTMLMediaElement.prototype,window.Element.prototype,fn],"innerHTML"),vn=Object.defineProperty({},"src",{get(){return this.hasAttribute("src")?fi(window.Element.prototype.getAttribute.call(this,"src")):""},set(e){return window.Element.prototype.setAttribute.call(this,"src",e),e}});class b extends v{constructor(e,t){super(e,t);t=e.source;let i=!1;if(this.featuresVideoFrameCallback=this.featuresVideoFrameCallback&&"VIDEO"===this.el_.tagName,t&&(this.el_.currentSrc!==t.src||e.tag&&3===e.tag.initNetworkState_)?this.setSource(t):this.handleLateInit_(this.el_),e.enableSourceset&&this.setupSourcesetHandling_(),this.isScrubbing_=!1,this.el_.hasChildNodes()){var s=this.el_.childNodes;let e=s.length;for(var r=[];e--;){var n=s[e];"track"===n.nodeName.toLowerCase()&&(this.featuresNativeTextTracks?(this.remoteTextTrackEls().addTrackElement_(n),this.remoteTextTracks().addTrack(n.track),this.textTracks().addTrack(n.track),i||this.el_.hasAttribute("crossorigin")||!yi(n.src)||(i=!0)):r.push(n))}for(let e=0;e{s=[];for(let e=0;ei.removeEventListener("change",e)),()=>{for(let e=0;e{i.removeEventListener("change",e),i.removeEventListener("change",r),i.addEventListener("change",r)}),this.on("webkitendfullscreen",()=>{i.removeEventListener("change",e),i.addEventListener("change",e),i.removeEventListener("change",r)})}overrideNative_(e,i){if(i===this[`featuresNative${e}Tracks`]){let t=e.toLowerCase();this[t+"TracksListeners_"]&&Object.keys(this[t+"TracksListeners_"]).forEach(e=>{this.el()[t+"Tracks"].removeEventListener(e,this[t+"TracksListeners_"][e])}),this[`featuresNative${e}Tracks`]=!i,this[t+"TracksListeners_"]=null,this.proxyNativeTracksForType_(t)}}overrideNativeAudioTracks(e){this.overrideNative_("Audio",e)}overrideNativeVideoTracks(e){this.overrideNative_("Video",e)}proxyNativeTracksForType_(i){var s=Hi[i];let r=this.el()[s.getterName],n=this[s.getterName]();if(this[`featuresNative${s.capitalName}Tracks`]&&r&&r.addEventListener){let e={change:e=>{var t={type:"change",target:n,currentTarget:n,srcElement:n};n.trigger(t),"text"===i&&this[zi.remoteText.getterName]().trigger(t)},addtrack(e){n.addTrack(e.track)},removetrack(e){n.removeTrack(e.track)}},t=function(){var e=[];for(let i=0;i{let i=e[t];r.addEventListener(t,i),this.on("dispose",e=>r.removeEventListener(t,i))}),this.on("loadstart",t),this.on("dispose",e=>this.off("loadstart",t))}}proxyNativeTracks_(){Hi.names.forEach(e=>{this.proxyNativeTracksForType_(e)})}createEl(){let t=this.options_.tag;t&&(this.options_.playerElIngest||this.movingMediaElementInDOM)||(t?(e=t.cloneNode(!0),t.parentNode&&t.parentNode.insertBefore(e,t),b.disposeMediaElement(t),t=e):(t=document.createElement("video"),e=d({},this.options_.tag&&Ne(this.options_.tag)),ve&&!0===this.options_.nativeControlsForTouch||delete e.controls,Re(t,Object.assign(e,{id:this.options_.techId,class:"vjs-tech"}))),t.playerId=this.options_.playerId),"undefined"!=typeof this.options_.preload&&Ue(t,"preload",this.options_.preload),void 0!==this.options_.disablePictureInPicture&&(t.disablePictureInPicture=this.options_.disablePictureInPicture);var e,i=["loop","muted","playsinline","autoplay"];for(let e=0;e{0{this.off("webkitbeginfullscreen",t),this.off("webkitendfullscreen",e)})}}supportsFullScreen(){return"function"==typeof this.el_.webkitEnterFullScreen}enterFullScreen(){let e=this.el_;if(e.paused&&e.networkState<=e.HAVE_METADATA)Kt(this.el_.play()),this.setTimeout(function(){e.pause();try{e.webkitEnterFullScreen()}catch(e){this.trigger("fullscreenerror",e)}},0);else try{e.webkitEnterFullScreen()}catch(e){this.trigger("fullscreenerror",e)}}exitFullScreen(){this.el_.webkitDisplayingFullscreen?this.el_.webkitExitFullScreen():this.trigger("fullscreenerror",new Error("The video is not fullscreen"))}requestPictureInPicture(){return this.el_.requestPictureInPicture()}requestVideoFrameCallback(e){return this.featuresVideoFrameCallback&&!this.el_.webkitKeys?this.el_.requestVideoFrameCallback(e):super.requestVideoFrameCallback(e)}cancelVideoFrameCallback(e){this.featuresVideoFrameCallback&&!this.el_.webkitKeys?this.el_.cancelVideoFrameCallback(e):super.cancelVideoFrameCallback(e)}src(e){if(void 0===e)return this.el_.src;this.setSrc(e)}addSourceElement(e,t){return e?(e={src:e},t&&(e.type=t),t=l("source",{},e),this.el_.appendChild(t),!0):(o.error("Invalid source URL."),!1)}removeSourceElement(e){if(e){var t;for(t of this.el_.querySelectorAll("source"))if(t.src===e)return this.el_.removeChild(t),!0;o.warn("No matching source element found with src: "+e)}else o.error("Source URL is required to remove the source element.");return!1}reset(){b.resetMediaElement(this.el_)}currentSrc(){return this.currentSource_?this.currentSource_.src:this.el_.currentSrc}setControls(e){this.el_.controls=!!e}addTextTrack(e,t,i){return this.featuresNativeTextTracks?this.el_.addTextTrack(e,t,i):super.addTextTrack(e,t,i)}createRemoteTextTrack(e){var t;return this.featuresNativeTextTracks?(t=document.createElement("track"),e.kind&&(t.kind=e.kind),e.label&&(t.label=e.label),(e.language||e.srclang)&&(t.srclang=e.language||e.srclang),e.default&&(t.default=e.default),e.id&&(t.id=e.id),e.src&&(t.src=e.src),t):super.createRemoteTextTrack(e)}addRemoteTextTrack(e,t){e=super.addRemoteTextTrack(e,t);return this.featuresNativeTextTracks&&this.el().appendChild(e),e}removeRemoteTextTrack(t){if(super.removeRemoteTextTrack(t),this.featuresNativeTextTracks){var i=this.$$("track");let e=i.length;for(;e--;)t!==i[e]&&t!==i[e].track||this.el().removeChild(i[e])}}getVideoPlaybackQuality(){var e;return"function"==typeof this.el().getVideoPlaybackQuality?this.el().getVideoPlaybackQuality():(e={},"undefined"!=typeof this.el().webkitDroppedFrameCount&&"undefined"!=typeof this.el().webkitDecodedFrameCount&&(e.droppedVideoFrames=this.el().webkitDroppedFrameCount,e.totalVideoFrames=this.el().webkitDecodedFrameCount),window.performance&&(e.creationTime=window.performance.now()),e)}}Z(b,"TEST_VID",function(){var e,t;if(Ee())return e=document.createElement("video"),(t=document.createElement("track")).kind="captions",t.srclang="en",t.label="English",e.appendChild(t),e}),b.isSupported=function(){try{b.TEST_VID.volume=.5}catch(e){return!1}return!(!b.TEST_VID||!b.TEST_VID.canPlayType)},b.canPlayType=function(e){return b.TEST_VID.canPlayType(e)},b.canPlaySource=function(e,t){return b.canPlayType(e.type)},b.canControlVolume=function(){try{let e=b.TEST_VID.volume;b.TEST_VID.volume=e/2+.1;var t=e!==b.TEST_VID.volume;return t&&u?(window.setTimeout(()=>{b&&b.prototype&&(b.prototype.featuresVolumeControl=e!==b.TEST_VID.volume)}),!1):t}catch(e){return!1}},b.canMuteVolume=function(){try{var e=b.TEST_VID.muted;return b.TEST_VID.muted=!e,b.TEST_VID.muted?Ue(b.TEST_VID,"muted","muted"):Be(b.TEST_VID,"muted"),e!==b.TEST_VID.muted}catch(e){return!1}},b.canControlPlaybackRate=function(){if(se&&le&&he<58)return!1;try{var e=b.TEST_VID.playbackRate;return b.TEST_VID.playbackRate=e/2+.1,e!==b.TEST_VID.playbackRate}catch(e){return!1}},b.canOverrideAttributes=function(){try{var e=()=>{};Object.defineProperty(document.createElement("video"),"src",{get:e,set:e}),Object.defineProperty(document.createElement("audio"),"src",{get:e,set:e}),Object.defineProperty(document.createElement("video"),"innerHTML",{get:e,set:e}),Object.defineProperty(document.createElement("audio"),"innerHTML",{get:e,set:e})}catch(e){return!1}return!0},b.supportsNativeTextTracks=function(){return Te||u&&le},b.supportsNativeVideoTracks=function(){return!(!b.TEST_VID||!b.TEST_VID.videoTracks)},b.supportsNativeAudioTracks=function(){return!(!b.TEST_VID||!b.TEST_VID.audioTracks)},b.Events=["loadstart","suspend","abort","error","emptied","stalled","loadedmetadata","loadeddata","canplay","canplaythrough","playing","waiting","seeking","seeked","ended","durationchange","timeupdate","progress","play","pause","ratechange","resize","volumechange"],[["featuresMuteControl","canMuteVolume"],["featuresPlaybackRate","canControlPlaybackRate"],["featuresSourceset","canOverrideAttributes"],["featuresNativeTextTracks","supportsNativeTextTracks"],["featuresNativeVideoTracks","supportsNativeVideoTracks"],["featuresNativeAudioTracks","supportsNativeAudioTracks"]].forEach(function([e,t]){Z(b.prototype,e,()=>b[t](),!0)}),b.prototype.featuresVolumeControl=b.canControlVolume(),b.prototype.movingMediaElementInDOM=!u,b.prototype.featuresFullscreenResize=!0,b.prototype.featuresProgressEvents=!0,b.prototype.featuresTimeupdateEvents=!0,b.prototype.featuresVideoFrameCallback=!(!b.TEST_VID||!b.TEST_VID.requestVideoFrameCallback),b.disposeMediaElement=function(e){if(e){for(e.parentNode&&e.parentNode.removeChild(e);e.hasChildNodes();)e.removeChild(e.firstChild);if(e.removeAttribute("src"),"function"==typeof e.load)try{e.load()}catch(e){}}},b.resetMediaElement=function(t){if(t){var i=t.querySelectorAll("source");let e=i.length;for(;e--;)t.removeChild(i[e]);if(t.removeAttribute("src"),"function"==typeof t.load)try{t.load()}catch(e){}}},["muted","defaultMuted","autoplay","controls","loop","playsinline"].forEach(function(e){b.prototype[e]=function(){return this.el_[e]||this.el_.hasAttribute(e)}}),["muted","defaultMuted","autoplay","loop","playsinline"].forEach(function(t){b.prototype["set"+m(t)]=function(e){(this.el_[t]=e)?this.el_.setAttribute(t,t):this.el_.removeAttribute(t)}}),["paused","currentTime","buffered","volume","poster","preload","error","seeking","seekable","ended","playbackRate","defaultPlaybackRate","disablePictureInPicture","played","networkState","readyState","videoWidth","videoHeight","crossOrigin"].forEach(function(e){b.prototype[e]=function(){return this.el_[e]}}),["volume","src","poster","preload","playbackRate","defaultPlaybackRate","disablePictureInPicture","crossOrigin"].forEach(function(t){b.prototype["set"+m(t)]=function(e){this.el_[t]=e}}),["pause","load","play"].forEach(function(e){b.prototype[e]=function(){return this.el_[e]()}}),v.withSourceHandlers(b),b.nativeSourceHandler={},b.nativeSourceHandler.canPlayType=function(e){try{return b.TEST_VID.canPlayType(e)}catch(e){return""}},b.nativeSourceHandler.canHandleSource=function(e,t){return e.type?b.nativeSourceHandler.canPlayType(e.type):e.src?(e=_i(e.src),b.nativeSourceHandler.canPlayType("video/"+e)):""},b.nativeSourceHandler.handleSource=function(e,t,i){t.setSrc(e.src)},b.nativeSourceHandler.dispose=function(){},b.registerSourceHandler(b.nativeSourceHandler),v.registerTech("Html5",b);let bn=["progress","abort","suspend","emptied","stalled","loadedmetadata","loadeddata","timeupdate","resize","volumechange","texttrackchange"],Tn={canplay:"CanPlay",canplaythrough:"CanPlayThrough",playing:"Playing",seeked:"Seeked"},Sn=["tiny","xsmall","small","medium","large","xlarge","huge"],wn={},En=(Sn.forEach(e=>{var t="x"===e.charAt(0)?"x-"+e.substring(1):e;wn[e]="vjs-layout-"+t}),{tiny:210,xsmall:320,small:425,medium:768,large:1440,xlarge:2560,huge:1/0});class T extends g{constructor(e,i,t){if(e.id=e.id||i.id||"vjs_video_"+lt++,(i=Object.assign(T.getTagSettings(e),i)).initChildren=!1,i.createEl=!1,i.evented=!1,i.reportTouchActivity=!1,i.language||(s=e.closest("[lang]"))&&(i.language=s.getAttribute("lang")),super(null,i,t),this.boundDocumentFullscreenChange_=e=>this.documentFullscreenChange_(e),this.boundFullWindowOnEscKey_=e=>this.fullWindowOnEscKey(e),this.boundUpdateStyleEl_=e=>this.updateStyleEl_(e),this.boundApplyInitTime_=e=>this.applyInitTime_(e),this.boundUpdateCurrentBreakpoint_=e=>this.updateCurrentBreakpoint_(e),this.boundHandleTechClick_=e=>this.handleTechClick_(e),this.boundHandleTechDoubleClick_=e=>this.handleTechDoubleClick_(e),this.boundHandleTechTouchStart_=e=>this.handleTechTouchStart_(e),this.boundHandleTechTouchMove_=e=>this.handleTechTouchMove_(e),this.boundHandleTechTouchEnd_=e=>this.handleTechTouchEnd_(e),this.boundHandleTechTap_=e=>this.handleTechTap_(e),this.boundUpdatePlayerHeightOnAudioOnlyMode_=e=>this.updatePlayerHeightOnAudioOnlyMode_(e),this.isFullscreen_=!1,this.log=W(this.id_),this.fsApi_=q,this.isPosterFromTech_=!1,this.queuedCallbacks_=[],this.isReady_=!1,this.hasStarted_=!1,this.userActive_=!1,this.debugEnabled_=!1,this.audioOnlyMode_=!1,this.audioPosterMode_=!1,this.audioOnlyCache_={controlBarHeight:null,playerHeight:null,hiddenChildren:[]},!this.options_||!this.options_.techOrder||!this.options_.techOrder.length)throw new Error("No techOrder specified. Did you overwrite videojs.options instead of just changing the properties you want to override?");if(this.tag=e,this.tagAttributes=e&&Ne(e),this.language(this.options_.language),i.languages){let t={};Object.getOwnPropertyNames(i.languages).forEach(function(e){t[e.toLowerCase()]=i.languages[e]}),this.languages_=t}else this.languages_=T.prototype.options_.languages;this.resetCache_(),this.poster_=i.poster||"",this.controls_=!!i.controls,e.controls=!1,e.removeAttribute("controls"),this.changingSrc_=!1,this.playCallbacks_=[],this.playTerminatedQueue_=[],e.hasAttribute("autoplay")?this.autoplay(!0):this.autoplay(this.options_.autoplay),i.plugins&&Object.keys(i.plugins).forEach(e=>{if("function"!=typeof this[e])throw new Error(`plugin "${e}" does not exist`)}),this.scrubbing_=!1,this.el_=this.createEl(),Ot(this,{eventBusKey:"el_"}),this.fsApi_.requestFullscreen&&(mt(document,this.fsApi_.fullscreenchange,this.boundDocumentFullscreenChange_),this.on(this.fsApi_.fullscreenchange,this.boundDocumentFullscreenChange_)),this.fluid_&&this.on(["playerreset","resize"],this.boundUpdateStyleEl_);var s=d(this.options_),t=(i.plugins&&Object.keys(i.plugins).forEach(e=>{this[e](i.plugins[e])}),i.debug&&this.debug(!0),this.options_.playerOptions=s,this.middleware_=[],this.playbackRates(i.playbackRates),i.experimentalSvgIcons&&((t=(new window.DOMParser).parseFromString('\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n',"image/svg+xml")).querySelector("parsererror")?(o.warn("Failed to load SVG Icons. Falling back to Font Icons."),this.options_.experimentalSvgIcons=null):((s=t.documentElement).style.display="none",this.el_.appendChild(s),this.addClass("vjs-svg-icons-enabled"))),this.initChildren(),this.isAudio("audio"===e.nodeName.toLowerCase()),this.controls()?this.addClass("vjs-controls-enabled"):this.addClass("vjs-controls-disabled"),this.el_.setAttribute("role","region"),this.isAudio()?this.el_.setAttribute("aria-label",this.localize("Audio Player")):this.el_.setAttribute("aria-label",this.localize("Video Player")),this.isAudio()&&this.addClass("vjs-audio"),i.spatialNavigation&&i.spatialNavigation.enabled&&(this.spatialNavigation=new Ns(this),this.addClass("vjs-spatial-navigation-enabled")),ve&&this.addClass("vjs-touch-enabled"),u||this.addClass("vjs-workinghover"),T.players[this.id_]=this,M.split(".")[0]);this.addClass("vjs-v"+t),this.userActive(!0),this.reportUserActivity(),this.one("play",e=>this.listenForUserActivity_(e)),this.on("keydown",e=>this.handleKeyDown(e)),this.on("languagechange",e=>this.handleLanguagechange(e)),this.breakpoints(this.options_.breakpoints),this.responsive(this.options_.responsive),this.on("ready",()=>{this.audioPosterMode(this.options_.audioPosterMode),this.audioOnlyMode(this.options_.audioOnlyMode)})}dispose(){var e;this.trigger("dispose"),this.off("dispose"),c(document,this.fsApi_.fullscreenchange,this.boundDocumentFullscreenChange_),c(document,"keydown",this.boundFullWindowOnEscKey_),this.styleEl_&&this.styleEl_.parentNode&&(this.styleEl_.parentNode.removeChild(this.styleEl_),this.styleEl_=null),T.players[this.id_]=null,this.tag&&this.tag.player&&(this.tag.player=null),this.el_&&this.el_.player&&(this.el_.player=null),this.tech_&&(this.tech_.dispose(),this.isPosterFromTech_=!1,this.poster_=""),this.playerElIngest_&&(this.playerElIngest_=null),this.tag&&(this.tag=null),e=this,Ts.hasOwnProperty(e.id())&&delete Ts[e.id()],a.names.forEach(e=>{e=this[a[e].getterName]();e&&e.off&&e.off()}),super.dispose({restoreEl:this.options_.restoreEl})}createEl(){let t=this.tag,i,e=this.playerElIngest_=t.parentNode&&t.parentNode.hasAttribute&&t.parentNode.hasAttribute("data-vjs-player"),s="video-js"===this.tag.tagName.toLowerCase(),r=(e?i=this.el_=t.parentNode:s||(i=this.el_=super.createEl("div")),Ne(t));if(s){for(i=this.el_=t,t=this.tag=document.createElement("video");i.children.length;)t.appendChild(i.firstChild);De(i,"video-js")||Pe(i,"video-js"),i.appendChild(t),e=this.playerElIngest_=i,Object.keys(i).forEach(e=>{try{t[e]=i[e]}catch(e){}})}t.setAttribute("tabindex","-1"),r.tabindex="-1",le&&pe&&(t.setAttribute("role","application"),r.role="application"),t.removeAttribute("width"),t.removeAttribute("height"),"width"in r&&delete r.width,"height"in r&&delete r.height,Object.getOwnPropertyNames(r).forEach(function(e){s&&"class"===e||i.setAttribute(e,r[e]),s&&t.setAttribute(e,r[e])}),t.playerId=t.id,t.id+="_html5_api",t.className="vjs-tech",(t.player=i.player=this).addClass("vjs-paused");var n,a=["IS_SMART_TV","IS_TIZEN","IS_WEBOS","IS_ANDROID","IS_IPAD","IS_IPHONE","IS_CHROMECAST_RECEIVER"].filter(e=>Se[e]).map(e=>"vjs-device-"+e.substring(3).toLowerCase().replace(/\_/g,"-")),o=(this.addClass(...a),!0!==window.VIDEOJS_NO_DYNAMIC_STYLE&&(this.styleEl_=at("vjs-styles-dimensions"),a=Ye(".vjs-styles-defaults"),(n=Ye("head")).insertBefore(this.styleEl_,a?a.nextSibling:n.firstChild)),this.fill_=!1,this.fluid_=!1,this.width(this.options_.width),this.height(this.options_.height),this.fill(this.options_.fill),this.fluid(this.options_.fluid),this.aspectRatio(this.options_.aspectRatio),this.crossOrigin(this.options_.crossOrigin||this.options_.crossorigin),t.getElementsByTagName("a"));for(let e=0;e{this.on(["playerreset","resize"],this.boundUpdateStyleEl_)},Ct(e)?t():(e.eventedCallbacks||(e.eventedCallbacks=[]),e.eventedCallbacks.push(t))):this.removeClass("vjs-fluid"),this.updateStyleEl_()}fill(e){if(void 0===e)return!!this.fill_;this.fill_=!!e,e?(this.addClass("vjs-fill"),this.fluid(!1)):this.removeClass("vjs-fill")}aspectRatio(e){if(void 0===e)return this.aspectRatio_;if(!/^\d+\:\d+$/.test(e))throw new Error("Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.");this.aspectRatio_=e,this.fluid(!0),this.updateStyleEl_()}updateStyleEl_(){if(!0===window.VIDEOJS_NO_DYNAMIC_STYLE){let e="number"==typeof this.width_?this.width_:this.options_.width,t="number"==typeof this.height_?this.height_:this.options_.height;var r=this.tech_&&this.tech_.el();void(r&&(0<=e&&(r.width=e),0<=t)&&(r.height=t))}else{let e,t,i,s;r=(i=void 0!==this.aspectRatio_&&"auto"!==this.aspectRatio_?this.aspectRatio_:0{e=a[e];n[e.getterName]=this[e.privateName]}),Object.assign(n,this.options_[i]),Object.assign(n,this.options_[s]),Object.assign(n,this.options_[e.toLowerCase()]),this.tag&&(n.tag=this.tag),t&&t.src===this.cache_.src&&0{this.on(this.tech_,t,e=>this[`handleTech${m(t)}_`](e))}),Object.keys(Tn).forEach(t=>{this.on(this.tech_,t,e=>{0===this.tech_.playbackRate()&&this.tech_.seeking()?this.queuedCallbacks_.push({callback:this[`handleTech${Tn[t]}_`].bind(this),event:e}):this[`handleTech${Tn[t]}_`](e)})}),this.on(this.tech_,"loadstart",e=>this.handleTechLoadStart_(e)),this.on(this.tech_,"sourceset",e=>this.handleTechSourceset_(e)),this.on(this.tech_,"waiting",e=>this.handleTechWaiting_(e)),this.on(this.tech_,"ended",e=>this.handleTechEnded_(e)),this.on(this.tech_,"seeking",e=>this.handleTechSeeking_(e)),this.on(this.tech_,"play",e=>this.handleTechPlay_(e)),this.on(this.tech_,"pause",e=>this.handleTechPause_(e)),this.on(this.tech_,"durationchange",e=>this.handleTechDurationChange_(e)),this.on(this.tech_,"fullscreenchange",(e,t)=>this.handleTechFullscreenChange_(e,t)),this.on(this.tech_,"fullscreenerror",(e,t)=>this.handleTechFullscreenError_(e,t)),this.on(this.tech_,"enterpictureinpicture",e=>this.handleTechEnterPictureInPicture_(e)),this.on(this.tech_,"leavepictureinpicture",e=>this.handleTechLeavePictureInPicture_(e)),this.on(this.tech_,"error",e=>this.handleTechError_(e)),this.on(this.tech_,"posterchange",e=>this.handleTechPosterChange_(e)),this.on(this.tech_,"textdata",e=>this.handleTechTextData_(e)),this.on(this.tech_,"ratechange",e=>this.handleTechRateChange_(e)),this.on(this.tech_,"loadedmetadata",this.boundUpdateStyleEl_),this.usingNativeControls(this.techGet_("controls")),this.controls()&&!this.usingNativeControls()&&this.addTechControlsListeners_(),this.tech_.el().parentNode===this.el()||"Html5"===i&&this.tag||Ae(this.tech_.el(),this.el()),this.tag&&(this.tag.player=null,this.tag=null)}unloadTech_(){a.names.forEach(e=>{e=a[e];this[e.privateName]=this[e.getterName]()}),this.textTracksJson_=Jt(this.tech_),this.isReady_=!1,this.tech_.dispose(),this.tech_=!1,this.isPosterFromTech_&&(this.poster_="",this.trigger("posterchange")),this.isPosterFromTech_=!1}tech(e){return void 0===e&&o.warn("Using the tech directly can be dangerous. I hope you know what you're doing.\nSee https://github.com/videojs/video.js/issues/2617 for more info.\n"),this.tech_}version(){return{"video.js":M}}addTechControlsListeners_(){this.removeTechControlsListeners_(),this.on(this.tech_,"click",this.boundHandleTechClick_),this.on(this.tech_,"dblclick",this.boundHandleTechDoubleClick_),this.on(this.tech_,"touchstart",this.boundHandleTechTouchStart_),this.on(this.tech_,"touchmove",this.boundHandleTechTouchMove_),this.on(this.tech_,"touchend",this.boundHandleTechTouchEnd_),this.on(this.tech_,"tap",this.boundHandleTechTap_)}removeTechControlsListeners_(){this.off(this.tech_,"tap",this.boundHandleTechTap_),this.off(this.tech_,"touchstart",this.boundHandleTechTouchStart_),this.off(this.tech_,"touchmove",this.boundHandleTechTouchMove_),this.off(this.tech_,"touchend",this.boundHandleTechTouchEnd_),this.off(this.tech_,"click",this.boundHandleTechClick_),this.off(this.tech_,"dblclick",this.boundHandleTechDoubleClick_)}handleTechReady_(){this.triggerReady(),this.cache_.volume&&this.techCall_("setVolume",this.cache_.volume),this.handleTechPosterChange_(),this.handleTechDurationChange_()}handleTechLoadStart_(){this.removeClass("vjs-ended","vjs-seeking"),this.error(null),this.handleTechDurationChange_(),this.paused()&&this.hasStarted(!1),this.trigger("loadstart"),this.manualAutoplay_(!0===this.autoplay()&&this.options_.normalizeAutoplay?"play":this.autoplay())}manualAutoplay_(t){if(this.tech_&&"string"==typeof t){var i=()=>{let e=this.muted(),t=(this.muted(!0),()=>{this.muted(e)});this.playTerminatedQueue_.push(t);var i=this.play();if(Xt(i))return i.catch(e=>{throw t(),new Error("Rejection at manualAutoplay. Restoring muted value. "+(e||""))})};let e;if("any"!==t||this.muted()?e="muted"!==t||this.muted()?this.play():i():Xt(e=this.play())&&(e=e.catch(i)),Xt(e))return e.then(()=>{this.trigger({type:"autoplay-success",autoplay:t})}).catch(()=>{this.trigger({type:"autoplay-failure",autoplay:t})})}}updateSourceCaches_(e=""){let t=e,i="";"string"!=typeof t&&(t=e.src,i=e.type),this.cache_.source=this.cache_.source||{},this.cache_.sources=this.cache_.sources||[],t&&!i&&(i=((e,t)=>{if(!t)return"";if(e.cache_.source.src===t&&e.cache_.source.type)return e.cache_.source.type;var i=e.cache_.sources.filter(e=>e.src===t);if(i.length)return i[0].type;var s=e.$$("source");for(let e=0;ee.src&&e.src===t),s=[],r=this.$$("source"),n=[];for(let e=0;ethis.updateSourceCaches_(e);var i=this.currentSource().src,s=t.src;(e=!i||/^blob:/.test(i)||!/^blob:/.test(s)||this.lastSource_&&(this.lastSource_.tech===s||this.lastSource_.player===i)?e:()=>{})(s),t.src||this.tech_.any(["sourceset","loadstart"],e=>{"sourceset"!==e.type&&(e=this.techGet_("currentSrc"),this.lastSource_.tech=e,this.updateSourceCaches_(e))})}this.lastSource_={player:this.currentSource().src,tech:t.src},this.trigger({src:t.src,type:"sourceset"})}hasStarted(e){if(void 0===e)return this.hasStarted_;e!==this.hasStarted_&&(this.hasStarted_=e,this.hasStarted_?this.addClass("vjs-has-started"):this.removeClass("vjs-has-started"))}handleTechPlay_(){this.removeClass("vjs-ended","vjs-paused"),this.addClass("vjs-playing"),this.hasStarted(!0),this.trigger("play")}handleTechRateChange_(){0e.callback(e.event)),this.queuedCallbacks_=[]),this.cache_.lastPlaybackRate=this.tech_.playbackRate(),this.trigger("ratechange")}handleTechWaiting_(){this.addClass("vjs-waiting"),this.trigger("waiting");let e=this.currentTime(),t=()=>{e!==this.currentTime()&&(this.removeClass("vjs-waiting"),this.off("timeupdate",t))};this.on("timeupdate",t)}handleTechCanPlay_(){this.removeClass("vjs-waiting"),this.trigger("canplay")}handleTechCanPlayThrough_(){this.removeClass("vjs-waiting"),this.trigger("canplaythrough")}handleTechPlaying_(){this.removeClass("vjs-waiting"),this.trigger("playing")}handleTechSeeking_(){this.addClass("vjs-seeking"),this.trigger("seeking")}handleTechSeeked_(){this.removeClass("vjs-seeking","vjs-ended"),this.trigger("seeked")}handleTechPause_(){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.trigger("pause")}handleTechEnded_(){this.addClass("vjs-ended"),this.removeClass("vjs-waiting"),this.options_.loop?(this.currentTime(0),this.play()):this.paused()||this.pause(),this.trigger("ended")}handleTechDurationChange_(){this.duration(this.techGet_("duration"))}handleTechClick_(e){!this.controls_||void 0!==this.options_&&void 0!==this.options_.userActions&&void 0!==this.options_.userActions.click&&!1===this.options_.userActions.click||(void 0!==this.options_&&void 0!==this.options_.userActions&&"function"==typeof this.options_.userActions.click?this.options_.userActions.click.call(this,e):this.paused()?Kt(this.play()):this.pause())}handleTechDoubleClick_(t){!this.controls_||Array.prototype.some.call(this.$$(".vjs-control-bar, .vjs-modal-dialog"),e=>e.contains(t.target))||void 0!==this.options_&&void 0!==this.options_.userActions&&void 0!==this.options_.userActions.doubleClick&&!1===this.options_.userActions.doubleClick||(void 0!==this.options_&&void 0!==this.options_.userActions&&"function"==typeof this.options_.userActions.doubleClick?this.options_.userActions.doubleClick.call(this,t):this.isInPictureInPicture()&&!document.pictureInPictureElement?this.exitPictureInPicture():this.isFullscreen()?this.exitFullscreen():this.requestFullscreen())}handleTechTap_(){this.userActive(!this.userActive())}handleTechTouchStart_(){this.userWasActive=this.userActive()}handleTechTouchMove_(){this.userWasActive&&this.reportUserActivity()}handleTechTouchEnd_(e){e.cancelable&&e.preventDefault()}toggleFullscreenClass_(){this.isFullscreen()?this.addClass("vjs-fullscreen"):this.removeClass("vjs-fullscreen")}documentFullscreenChange_(t){t=t.target.player;if(!t||t===this){t=this.el();let e=document[this.fsApi_.fullscreenElement]===t;!e&&t.matches&&(e=t.matches(":"+this.fsApi_.fullscreen)),this.isFullscreen(e)}}handleTechFullscreenChange_(e,t){t&&(t.nativeIOSFullscreen&&(this.addClass("vjs-ios-native-fs"),this.tech_.one("webkitendfullscreen",()=>{this.removeClass("vjs-ios-native-fs")})),this.isFullscreen(t.isFullscreen))}handleTechFullscreenError_(e,t){this.trigger("fullscreenerror",t)}togglePictureInPictureClass_(){this.isInPictureInPicture()?this.addClass("vjs-picture-in-picture"):this.removeClass("vjs-picture-in-picture")}handleTechEnterPictureInPicture_(e){this.isInPictureInPicture(!0)}handleTechLeavePictureInPicture_(e){this.isInPictureInPicture(!1)}handleTechError_(){var e=this.tech_.error();e&&this.error(e)}handleTechTextData_(){let e=1{this.play_(e)})}play_(e=Kt){this.playCallbacks_.push(e);var t,e=Boolean(!this.changingSrc_&&(this.src()||this.currentSrc())),i=Boolean(Te||u);this.waitToPlay_&&(this.off(["ready","loadstart"],this.waitToPlay_),this.waitToPlay_=null),this.isReady_&&e?(t=this.techGet_("play"),i&&this.hasClass("vjs-ended")&&this.resetProgressBar_(),null===t?this.runPlayTerminatedQueue_():this.runPlayCallbacks_(t)):(this.waitToPlay_=e=>{this.play_()},this.one(["ready","loadstart"],this.waitToPlay_),!e&&i&&this.load())}runPlayTerminatedQueue_(){var e=this.playTerminatedQueue_.slice(0);this.playTerminatedQueue_=[],e.forEach(function(e){e()})}runPlayCallbacks_(t){var e=this.playCallbacks_.slice(0);this.playCallbacks_=[],this.playTerminatedQueue_=[],e.forEach(function(e){e(t)})}pause(){this.techCall_("pause")}paused(){return!1!==this.techGet_("paused")}played(){return this.techGet_("played")||jt(0,0)}scrubbing(e){if("undefined"==typeof e)return this.scrubbing_;this.scrubbing_=!!e,this.techCall_("setScrubbing",this.scrubbing_),e?this.addClass("vjs-scrubbing"):this.removeClass("vjs-scrubbing")}currentTime(e){if(void 0===e)return this.cache_.currentTime=this.techGet_("currentTime")||0,this.cache_.currentTime;e<0&&(e=0),this.isReady_&&!this.changingSrc_&&this.tech_&&this.tech_.isReady_?(this.techCall_("setCurrentTime",e),this.cache_.initTime=0,isFinite(e)&&(this.cache_.currentTime=Number(e))):(this.cache_.initTime=e,this.off("canplay",this.boundApplyInitTime_),this.one("canplay",this.boundApplyInitTime_))}applyInitTime_(){this.currentTime(this.cache_.initTime)}duration(e){if(void 0===e)return void 0!==this.cache_.duration?this.cache_.duration:NaN;(e=(e=parseFloat(e))<0?1/0:e)!==this.cache_.duration&&((this.cache_.duration=e)===1/0?this.addClass("vjs-live"):this.removeClass("vjs-live"),isNaN(e)||this.trigger("durationchange"))}remainingTime(){return this.duration()-this.currentTime()}remainingTimeDisplay(){return Math.floor(this.duration())-Math.floor(this.currentTime())}buffered(){let e=this.techGet_("buffered");return e=e&&e.length?e:jt(0,0)}seekable(){let e=this.techGet_("seekable");return e=e&&e.length?e:jt(0,0)}seeking(){return this.techGet_("seeking")}ended(){return this.techGet_("ended")}networkState(){return this.techGet_("networkState")}readyState(){return this.techGet_("readyState")}bufferedPercent(){return Gt(this.buffered(),this.duration())}bufferedEnd(){var e=this.buffered(),t=this.duration();let i=e.end(e.length-1);return i=i>t?t:i}volume(e){let t;if(void 0===e)return t=parseFloat(this.techGet_("volume")),isNaN(t)?1:t;t=Math.max(0,Math.min(1,e)),this.cache_.volume=t,this.techCall_("setVolume",t),0{function s(){o.off("fullscreenerror",r),o.off("fullscreenchange",t)}function t(){s(),e()}function r(e,t){s(),i(t)}o.one("fullscreenchange",t),o.one("fullscreenerror",r);var n=o.requestFullscreenHelper_(a);n&&(n.then(s,s),n.then(e,i))})}requestFullscreenHelper_(e){let t;if(this.fsApi_.prefixed||(t=this.options_.fullscreen&&this.options_.fullscreen.options||{},void 0!==e&&(t=e)),this.fsApi_.requestFullscreen)return(e=this.el_[this.fsApi_.requestFullscreen](t))&&e.then(()=>this.isFullscreen(!0),()=>this.isFullscreen(!1)),e;this.tech_.supportsFullScreen()&&!0==!this.options_.preferFullWindow?this.techCall_("enterFullScreen"):this.enterFullWindow()}exitFullscreen(){let a=this;return new Promise((e,i)=>{function s(){a.off("fullscreenerror",r),a.off("fullscreenchange",t)}function t(){s(),e()}function r(e,t){s(),i(t)}a.one("fullscreenchange",t),a.one("fullscreenerror",r);var n=a.exitFullscreenHelper_();n&&(n.then(s,s),n.then(e,i))})}exitFullscreenHelper_(){var e;if(this.fsApi_.requestFullscreen)return(e=document[this.fsApi_.exitFullscreen]())&&Kt(e.then(()=>this.isFullscreen(!1))),e;this.tech_.supportsFullScreen()&&!0==!this.options_.preferFullWindow?this.techCall_("exitFullScreen"):this.exitFullWindow()}enterFullWindow(){this.isFullscreen(!0),this.isFullWindow=!0,this.docOrigOverflow=document.documentElement.style.overflow,mt(document,"keydown",this.boundFullWindowOnEscKey_),document.documentElement.style.overflow="hidden",Pe(document.body,"vjs-full-window"),this.trigger("enterFullWindow")}fullWindowOnEscKey(e){"Escape"===e.key&&!0===this.isFullscreen()&&(this.isFullWindow?this.exitFullWindow():this.exitFullscreen())}exitFullWindow(){this.isFullscreen(!1),this.isFullWindow=!1,c(document,"keydown",this.boundFullWindowOnEscKey_),document.documentElement.style.overflow=this.docOrigOverflow,Le(document.body,"vjs-full-window"),this.trigger("exitFullWindow")}disablePictureInPicture(e){if(void 0===e)return this.techGet_("disablePictureInPicture");this.techCall_("setDisablePictureInPicture",e),this.options_.disablePictureInPicture=e,this.trigger("disablepictureinpicturechanged")}isInPictureInPicture(e){if(void 0===e)return!!this.isInPictureInPicture_;this.isInPictureInPicture_=!!e,this.togglePictureInPictureClass_()}requestPictureInPicture(){if(this.options_.enableDocumentPictureInPicture&&window.documentPictureInPicture){let t=document.createElement(this.el().tagName);return t.classList=this.el().classList,t.classList.add("vjs-pip-container"),this.posterImage&&t.appendChild(this.posterImage.el().cloneNode(!0)),this.titleBar&&t.appendChild(this.titleBar.el().cloneNode(!0)),t.appendChild(l("p",{className:"vjs-pip-text"},{},this.localize("Playing in picture-in-picture"))),window.documentPictureInPicture.requestWindow({width:this.videoWidth(),height:this.videoHeight()}).then(e=>(Ze(e),this.el_.parentNode.insertBefore(t,this.el_),e.document.body.appendChild(this.el_),e.document.body.classList.add("vjs-pip-window"),this.player_.isInPictureInPicture(!0),this.player_.trigger({type:"enterpictureinpicture",pipWindow:e}),e.addEventListener("pagehide",e=>{e=e.target.querySelector(".video-js");t.parentNode.replaceChild(e,t),this.player_.isInPictureInPicture(!1),this.player_.trigger("leavepictureinpicture")}),e))}return"pictureInPictureEnabled"in document&&!1===this.disablePictureInPicture()?this.techGet_("requestPictureInPicture"):Promise.reject("No PiP mode is available")}exitPictureInPicture(){return window.documentPictureInPicture&&window.documentPictureInPicture.window?(window.documentPictureInPicture.window.close(),Promise.resolve()):"pictureInPictureEnabled"in document?document.exitPictureInPicture():void 0}handleKeyDown(e){var t,i,s=this.options_.userActions;s&&s.hotkeys&&(t=this.el_.ownerDocument.activeElement,i=t.tagName.toLowerCase(),t.isContentEditable||("input"===i?-1===["button","checkbox","hidden","radio","reset","submit"].indexOf(t.type):-1!==["textarea"].indexOf(i))||("function"==typeof s.hotkeys?s.hotkeys.call(this,e):this.handleHotkeys(e)))}handleHotkeys(t){var{fullscreenKey:e=e=>"f"===t.key.toLowerCase(),muteKey:i=e=>"m"===t.key.toLowerCase(),playPauseKey:s=e=>"k"===t.key.toLowerCase()||" "===t.key.toLowerCase()}=this.options_.userActions?this.options_.userActions.hotkeys:{};e.call(this,t)?(t.preventDefault(),t.stopPropagation(),e=g.getComponent("FullscreenToggle"),!1!==document[this.fsApi_.fullscreenEnabled]&&e.prototype.handleClick.call(this,t)):i.call(this,t)?(t.preventDefault(),t.stopPropagation(),g.getComponent("MuteToggle").prototype.handleClick.call(this,t)):s.call(this,t)&&(t.preventDefault(),t.stopPropagation(),g.getComponent("PlayToggle").prototype.handleClick.call(this,t))}canPlayType(s){var r;for(let t=0,i=this.options_.techOrder;ti.some(e=>{if(r=s(t,e))return!0})),r}var i=this.options_.techOrder.map(e=>[e,v.getTech(e)]).filter(([e,t])=>t?t.isSupported():(o.error(`The "${e}" tech is undefined. Skipped browser support check for that tech.`),!1));let s;var r,n=([e,t],i)=>{if(t.canPlaySource(i,this.options_[e.toLowerCase()]))return{source:i,tech:e}};return(s=this.options_.sourceOrder?t(e,i,(r=n,(e,t)=>r(t,e))):t(i,e,n))||!1}handleSrc_(e,s){if("undefined"==typeof e)return this.cache_.src||"";this.resetRetryOnError_&&this.resetRetryOnError_();let r=Ds(e);if(r.length){if(this.changingSrc_=!0,s||(this.cache_.sources=r),this.updateSourceCaches_(r[0]),ws(this,r[0],(e,t)=>{var i;if(this.middleware_=t,s||(this.cache_.sources=r),this.updateSourceCaches_(e),this.src_(e))return 1e.setTech&&e.setTech(i))}),1{this.error(null),this.handleSrc_(r.slice(1),!0)},t=()=>{this.off("error",e)};this.one("error",e),this.one("playing",t),this.resetRetryOnError_=()=>{this.off("error",e),this.off("playing",t)}}}else this.setTimeout(function(){this.error({code:4,message:this.options_.notSupportedMessage})},0)}src(e){return this.handleSrc_(e,!1)}src_(e){var t=this.selectSource([e]);return!t||(Ut(t.tech,this.techName_)?this.ready(function(){this.tech_.constructor.prototype.hasOwnProperty("setSource")?this.techCall_("setSource",e):this.techCall_("src",e.src),this.changingSrc_=!1},!0):(this.changingSrc_=!0,this.loadTech_(t.tech,t.source),this.tech_.ready(()=>{this.changingSrc_=!1})),!1)}addSourceElement(e,t){return!!this.tech_&&this.tech_.addSourceElement(e,t)}removeSourceElement(e){return!!this.tech_&&this.tech_.removeSourceElement(e)}load(){this.tech_&&this.tech_.vhs?this.src(this.currentSource()):this.techCall_("load")}reset(){this.paused()?this.doReset_():Kt(this.play().then(()=>this.doReset_()))}doReset_(){this.tech_&&this.tech_.clearTracks("text"),this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.resetCache_(),this.poster(""),this.loadTech_(this.options_.techOrder[0],null),this.techCall_("reset"),this.resetControlBarUI_(),this.error(null),this.titleBar&&this.titleBar.update({title:void 0,description:void 0}),Ct(this)&&this.trigger("playerreset")}resetControlBarUI_(){this.resetProgressBar_(),this.resetPlaybackRate_(),this.resetVolumeBar_()}resetProgressBar_(){this.currentTime(0);var{currentTimeDisplay:e,durationDisplay:t,progressControl:i,remainingTimeDisplay:s}=this.controlBar||{},i=(i||{}).seekBar;e&&e.updateContent(),t&&t.updateContent(),s&&s.updateContent(),i&&(i.update(),i.loadProgressBar)&&i.loadProgressBar.update()}resetPlaybackRate_(){this.playbackRate(this.defaultPlaybackRate()),this.handleTechRateChange_()}resetVolumeBar_(){this.volume(1),this.trigger("volumechange")}currentSources(){var e=this.currentSource(),t=[];return 0!==Object.keys(e).length&&t.push(e),this.cache_.sources||t}currentSource(){return this.cache_.source||{}}currentSrc(){return this.currentSource()&&this.currentSource().src||""}currentType(){return this.currentSource()&&this.currentSource().type||""}preload(e){if(void 0===e)return this.techGet_("preload");this.techCall_("setPreload",e),this.options_.preload=e}autoplay(e){if(void 0===e)return this.options_.autoplay||!1;let t;"string"==typeof e&&/(any|play|muted)/.test(e)||!0===e&&this.options_.normalizeAutoplay?(this.options_.autoplay=e,this.manualAutoplay_("string"==typeof e?e:"play"),t=!1):this.options_.autoplay=!!e,t="undefined"==typeof t?this.options_.autoplay:t,this.tech_&&this.techCall_("setAutoplay",t)}playsinline(e){return void 0!==e&&(this.techCall_("setPlaysinline",e),this.options_.playsinline=e),this.techGet_("playsinline")}loop(e){if(void 0===e)return this.techGet_("loop");this.techCall_("setLoop",e),this.options_.loop=e}poster(e){if(void 0===e)return this.poster_;(e=e||"")!==this.poster_&&(this.poster_=e,this.techCall_("setPoster",e),this.isPosterFromTech_=!1,this.trigger("posterchange"))}handleTechPosterChange_(){var e;(!this.poster_||this.options_.techCanOverridePoster)&&this.tech_&&this.tech_.poster&&(e=this.tech_.poster()||"")!==this.poster_&&(this.poster_=e,this.isPosterFromTech_=!0,this.trigger("posterchange"))}controls(e){if(void 0===e)return!!this.controls_;this.controls_!==(e=!!e)&&(this.controls_=e,this.usingNativeControls()&&this.techCall_("setControls",e),this.controls_?(this.removeClass("vjs-controls-disabled"),this.addClass("vjs-controls-enabled"),this.trigger("controlsenabled"),this.usingNativeControls()||this.addTechControlsListeners_()):(this.removeClass("vjs-controls-enabled"),this.addClass("vjs-controls-disabled"),this.trigger("controlsdisabled"),this.usingNativeControls()||this.removeTechControlsListeners_()))}usingNativeControls(e){if(void 0===e)return!!this.usingNativeControls_;this.usingNativeControls_!==(e=!!e)&&(this.usingNativeControls_=e,this.usingNativeControls_?(this.addClass("vjs-using-native-controls"),this.trigger("usingnativecontrols")):(this.removeClass("vjs-using-native-controls"),this.trigger("usingcustomcontrols")))}error(t){if(void 0===t)return this.error_||null;if(B("beforeerror").forEach(e=>{e=e(this,t);Y(e)&&!Array.isArray(e)||"string"==typeof e||"number"==typeof e||null===e?t=e:this.log.error("please return a value that MediaError expects in beforeerror hooks")}),this.options_.suppressNotSupportedError&&t&&4===t.code){let e=function(){this.error(t)};this.options_.suppressNotSupportedError=!1,this.any(["click","touchstart"],e),void this.one("loadstart",function(){this.off(["click","touchstart"],e)})}else null===t?(this.error_=null,this.removeClass("vjs-error"),this.errorDisplay&&this.errorDisplay.close()):(this.error_=new i(t),this.addClass("vjs-error"),o.error(`(CODE:${this.error_.code} ${i.errorTypes[this.error_.code]})`,this.error_.message,this.error_),this.trigger("error"),B("error").forEach(e=>e(this,this.error_)))}reportUserActivity(e){this.userActivity_=!0}userActive(e){if(void 0===e)return this.userActive_;(e=!!e)!==this.userActive_&&(this.userActive_=e,this.userActive_?(this.userActivity_=!0,this.removeClass("vjs-user-inactive"),this.addClass("vjs-user-active"),this.trigger("useractive")):(this.tech_&&this.tech_.one("mousemove",function(e){e.stopPropagation(),e.preventDefault()}),this.userActivity_=!1,this.removeClass("vjs-user-active"),this.addClass("vjs-user-inactive"),this.trigger("userinactive")))}listenForUserActivity_(){let t,i,s,r=p(this,this.reportUserActivity);function e(e){r(),this.clearInterval(t)}this.on("mousedown",function(){r(),this.clearInterval(t),t=this.setInterval(r,250)}),this.on("mousemove",function(e){e.screenX===i&&e.screenY===s||(i=e.screenX,s=e.screenY,r())}),this.on("mouseup",e),this.on("mouseleave",e);var n=this.getChild("controlBar");!n||u||se||(n.on("mouseenter",function(e){0!==this.player().options_.inactivityTimeout&&(this.player().cache_.inactivityTimeout=this.player().options_.inactivityTimeout),this.player().options_.inactivityTimeout=0}),n.on("mouseleave",function(e){this.player().options_.inactivityTimeout=this.player().cache_.inactivityTimeout})),this.on("keydown",r),this.on("keyup",r);let a;this.setInterval(function(){var e;this.userActivity_&&(this.userActivity_=!1,this.userActive(!0),this.clearTimeout(a),(e=this.options_.inactivityTimeout)<=0||(a=this.setTimeout(function(){this.userActivity_||this.userActive(!1)},e)))},250)}playbackRate(e){if(void 0===e)return this.tech_&&this.tech_.featuresPlaybackRate?this.cache_.lastPlaybackRate||this.techGet_("playbackRate"):1;this.techCall_("setPlaybackRate",e)}defaultPlaybackRate(e){return void 0!==e?this.techCall_("setDefaultPlaybackRate",e):this.tech_&&this.tech_.featuresPlaybackRate?this.techGet_("defaultPlaybackRate"):1}isAudio(e){if(void 0===e)return!!this.isAudio_;this.isAudio_=!!e}updatePlayerHeightOnAudioOnlyMode_(){var e=this.getChild("ControlBar");e&&this.audioOnlyCache_.controlBarHeight!==e.currentHeight()&&(this.audioOnlyCache_.controlBarHeight=e.currentHeight(),this.height(this.audioOnlyCache_.controlBarHeight))}enableAudioOnlyUI_(){this.addClass("vjs-audio-only-mode");var e=this.children();let t=this.getChild("ControlBar");var i=t&&t.currentHeight();e.forEach(e=>{e!==t&&e.el_&&!e.hasClass("vjs-hidden")&&(e.hide(),this.audioOnlyCache_.hiddenChildren.push(e))}),this.audioOnlyCache_.playerHeight=this.currentHeight(),this.audioOnlyCache_.controlBarHeight=i,this.on("playerresize",this.boundUpdatePlayerHeightOnAudioOnlyMode_),this.height(i),this.trigger("audioonlymodechange")}disableAudioOnlyUI_(){this.removeClass("vjs-audio-only-mode"),this.off("playerresize",this.boundUpdatePlayerHeightOnAudioOnlyMode_),this.audioOnlyCache_.hiddenChildren.forEach(e=>e.show()),this.height(this.audioOnlyCache_.playerHeight),this.trigger("audioonlymodechange")}audioOnlyMode(e){return"boolean"!=typeof e||e===this.audioOnlyMode_?this.audioOnlyMode_:(this.audioOnlyMode_=e)?(e=[],this.isInPictureInPicture()&&e.push(this.exitPictureInPicture()),this.isFullscreen()&&e.push(this.exitFullscreen()),this.audioPosterMode()&&e.push(this.audioPosterMode(!1)),Promise.all(e).then(()=>this.enableAudioOnlyUI_())):Promise.resolve().then(()=>this.disableAudioOnlyUI_())}enablePosterModeUI_(){(this.tech_&&this.tech_).hide(),this.addClass("vjs-audio-poster-mode"),this.trigger("audiopostermodechange")}disablePosterModeUI_(){(this.tech_&&this.tech_).show(),this.removeClass("vjs-audio-poster-mode"),this.trigger("audiopostermodechange")}audioPosterMode(e){return"boolean"!=typeof e||e===this.audioPosterMode_?this.audioPosterMode_:(this.audioPosterMode_=e)?(this.audioOnlyMode()?this.audioOnlyMode(!1):Promise.resolve()).then(()=>{this.enablePosterModeUI_()}):Promise.resolve().then(()=>{this.disablePosterModeUI_()})}addTextTrack(e,t,i){if(this.tech_)return this.tech_.addTextTrack(e,t,i)}addRemoteTextTrack(e,t){if(this.tech_)return this.tech_.addRemoteTextTrack(e,t)}removeRemoteTextTrack(e={}){let t=e.track;if(t=t||e,this.tech_)return this.tech_.removeRemoteTextTrack(t)}getVideoPlaybackQuality(){return this.techGet_("getVideoPlaybackQuality")}videoWidth(){return this.tech_&&this.tech_.videoWidth&&this.tech_.videoWidth()||0}videoHeight(){return this.tech_&&this.tech_.videoHeight&&this.tech_.videoHeight()||0}language(e){if(void 0===e)return this.language_;this.language_!==String(e).toLowerCase()&&(this.language_=String(e).toLowerCase(),Ct(this))&&this.trigger("languagechange")}languages(){return d(T.prototype.options_.languages,this.languages_)}toJSON(){var t=d(this.options_),i=t.tracks;t.tracks=[];for(let e=0;e{this.removeChild(i)}),i.open(),i}updateCurrentBreakpoint_(){if(this.responsive()){var t=this.currentBreakpoint(),i=this.currentWidth();for(let e=0;ethis.addRemoteTextTrack(e,!1)),this.titleBar&&this.titleBar.update({title:l,description:r||e||""}),this.ready(t))}getMedia(){var e,t;return this.cache_.media?d(this.cache_.media):(e=this.poster(),t={src:this.currentSources(),textTracks:Array.prototype.map.call(this.remoteTextTracks(),e=>({kind:e.kind,label:e.label,language:e.language,src:e.src}))},e&&(t.poster=e,t.artwork=[{src:t.poster,type:Ls(t.poster)}]),t)}static getTagSettings(e){var i={sources:[],tracks:[]},t=Ne(e),s=t["data-setup"];if(De(e,"vjs-fill")&&(t.fill=!0),De(e,"vjs-fluid")&&(t.fluid=!0),null!==s)try{Object.assign(t,JSON.parse(s||"{}"))}catch(e){o.error("data-setup",e)}if(Object.assign(i,t),e.hasChildNodes()){var r=e.childNodes;for(let e=0,t=r.length;e"number"==typeof e)&&(this.cache_.playbackRates=e,this.trigger("playbackrateschange"))}}T.prototype.videoTracks=()=>{},T.prototype.audioTracks=()=>{},T.prototype.textTracks=()=>{},T.prototype.remoteTextTracks=()=>{},T.prototype.remoteTextTrackEls=()=>{},a.names.forEach(function(e){let t=a[e];T.prototype[t.getterName]=function(){return this.tech_?this.tech_[t.getterName]():(this[t.privateName]=this[t.privateName]||new t.ListClass,this[t.privateName])}}),T.prototype.crossorigin=T.prototype.crossOrigin,T.players={};Zr=window.navigator;T.prototype.options_={techOrder:v.defaultTechOrder_,html5:{},enableSourceset:!0,inactivityTimeout:2e3,playbackRates:[],liveui:!1,children:["mediaLoader","posterImage","titleBar","textTrackDisplay","loadingSpinner","bigPlayButton","liveTracker","controlBar","errorDisplay","textTrackSettings","resizeManager"],language:Zr&&(Zr.languages&&Zr.languages[0]||Zr.userLanguage||Zr.language)||"en",languages:{},notSupportedMessage:"No compatible source was found for this media.",normalizeAutoplay:!1,fullscreen:{options:{navigationUI:"hide"}},breakpoints:{},responsive:!1,audioOnlyMode:!1,audioPosterMode:!1,spatialNavigation:{enabled:!1,horizontalSeek:!1},enableSmoothSeeking:!1,disableSeekWhileScrubbingOnMobile:!1,disableSeekWhileScrubbingOnSTV:!1},bn.forEach(function(e){T.prototype[`handleTech${m(e)}_`]=function(){return this.trigger(e)}}),g.registerComponent("Player",T);function Cn(t,i){function s(){Ln(this,{name:t,plugin:i,instance:null},!0);var e=i.apply(this,arguments);return Pn(this,t),Ln(this,{name:t,plugin:i,instance:e}),e}return Object.keys(i).forEach(function(e){s[e]=i[e]}),s}let kn="plugin",In="activePlugins_",xn={},An=e=>xn.hasOwnProperty(e),Dn=e=>An(e)?xn[e]:void 0,Pn=(e,t)=>{e[In]=e[In]||{},e[In][t]=!0},Ln=(e,t,i)=>{i=(i?"before":"")+"pluginsetup";e.trigger(i,t),e.trigger(i+":"+t.name,t)},On=(i,s)=>(s.prototype.name=i,function(...e){Ln(this,{name:i,plugin:s,instance:null},!0);let t=new s(this,...e);return this[i]=()=>t,Ln(this,t.getEventHash()),t});class Rn{constructor(e){if(this.constructor===Rn)throw new Error("Plugin must be sub-classed; not directly instantiated.");this.player=e,this.log||(this.log=this.player.log.createLogger(this.name)),Ot(this),delete this.trigger,Nt(this,this.constructor.defaultState),Pn(e,this.name),this.dispose=this.dispose.bind(this),e.on("dispose",this.dispose)}version(){return this.constructor.VERSION}getEventHash(e={}){return e.name=this.name,e.plugin=this.constructor,e.instance=this,e}trigger(e,t={}){return gt(this.eventBusEl_,e,this.getEventHash(t))}handleStateChanged(e){}dispose(){var{name:e,player:t}=this;this.trigger("dispose"),this.off(),t.off("dispose",this.dispose),t[In][e]=!1,this.player=this.state=null,t[e]=On(e,xn[e])}static isBasic(e){e="string"==typeof e?Dn(e):e;return"function"==typeof e&&!Rn.prototype.isPrototypeOf(e.prototype)}static registerPlugin(e,t){if("string"!=typeof e)throw new Error(`Illegal plugin name, "${e}", must be a string, was ${typeof e}.`);if(An(e))o.warn(`A plugin named "${e}" already exists. You may want to avoid re-registering plugins!`);else if(T.prototype.hasOwnProperty(e))throw new Error(`Illegal plugin name, "${e}", cannot share a name with an existing player method!`);if("function"!=typeof t)throw new Error(`Illegal plugin for "${e}", must be a function, was ${typeof t}.`);return xn[e]=t,e!==kn&&(Rn.isBasic(t)?T.prototype[e]=Cn(e,t):T.prototype[e]=On(e,t)),t}static deregisterPlugin(e){if(e===kn)throw new Error("Cannot de-register base plugin.");An(e)&&(delete xn[e],delete T.prototype[e])}static getPlugins(e=Object.keys(xn)){let i;return e.forEach(e=>{var t=Dn(e);t&&((i=i||{})[e]=t)}),i}static getPluginVersion(e){e=Dn(e);return e&&e.VERSION||""}}function Nn(e,i,s,r){{var n=i+` is deprecated and will be removed in ${e}.0; please use ${s} instead.`,a=r;let t=!1;return function(...e){return t||o.warn(n),t=!0,a.apply(this,e)}}}Rn.getPlugin=Dn,Rn.BASE_PLUGIN_NAME=kn,Rn.registerPlugin(kn,Rn),T.prototype.usingPlugin=function(e){return!!this[In]&&!0===this[In][e]},T.prototype.hasPlugin=function(e){return!!An(e)};let Mn=e=>0===e.indexOf("#")?e.slice(1):e;function E(e,i,s){let r=E.getPlayer(e);if(r)i&&o.warn(`Player "${e}" is already initialised. Options will not be applied.`),s&&r.ready(s);else{let t="string"==typeof e?Ye("#"+Mn(e)):e;if(!Ce(t))throw new TypeError("The element or ID supplied is not valid. (videojs)");e="getRootNode"in t&&t.getRootNode()instanceof window.ShadowRoot?t.getRootNode():t.ownerDocument.body,e=(t.ownerDocument.defaultView&&e.contains(t)||o.warn("The element supplied is not included in the DOM"),!0===(i=i||{}).restoreEl&&(i.restoreEl=(t.parentNode&&t.parentNode.hasAttribute&&t.parentNode.hasAttribute("data-vjs-player")?t.parentNode:t).cloneNode(!0)),B("beforesetup").forEach(e=>{e=e(t,d(i));!Y(e)||Array.isArray(e)?o.error("please return an object in beforesetup hooks"):i=d(i,e)}),g.getComponent("Player"));r=new e(t,i,s),B("setup").forEach(e=>e(r))}return r}E.hooks_=U,E.hooks=B,E.hook=function(e,t){B(e,t)},E.hookOnce=function(s,e){B(s,[].concat(e).map(t=>{let i=(...e)=>(F(s,i),t(...e));return i}))},E.removeHook=F,!0!==window.VIDEOJS_NO_DYNAMIC_STYLE&&Ee()&&!(e=Ye(".vjs-styles-defaults"))&&(e=at("vjs-styles-defaults"),(Jr=Ye("head"))&&Jr.insertBefore(e,Jr.firstChild),ot(e,` + .video-js { + width: 300px; + height: 150px; + } + + .vjs-fluid:not(.vjs-audio-only-mode) { + padding-top: 56.25% + } + `)),rt(1,E),E.VERSION=M,E.options=T.prototype.options_,E.getPlayers=()=>T.players,E.getPlayer=e=>{var t=T.players;let i;if("string"==typeof e){var s=Mn(e),r=t[s];if(r)return r;i=Ye("#"+s)}else i=e;if(Ce(i)){var{player:r,playerId:s}=i;if(r||t[s])return r||t[s]}},E.getAllPlayers=()=>Object.keys(T.players).map(e=>T.players[e]).filter(Boolean),E.players=T.players,E.getComponent=g.getComponent,E.registerComponent=(e,t)=>(v.isTech(t)&&o.warn(`The ${e} tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)`),g.registerComponent.call(g,e,t)),E.getTech=v.getTech,E.registerTech=v.registerTech,E.use=function(e,t){bs[e]=bs[e]||[],bs[e].push(t)},Object.defineProperty(E,"middleware",{value:{},writeable:!1,enumerable:!0}),Object.defineProperty(E.middleware,"TERMINATOR",{value:Ss,writeable:!1,enumerable:!0}),E.browser=Se,E.obj=ee,E.mergeOptions=Nn(9,"videojs.mergeOptions","videojs.obj.merge",d),E.defineLazyProperty=Nn(9,"videojs.defineLazyProperty","videojs.obj.defineLazyProperty",Z),E.bind=Nn(9,"videojs.bind","native Function.prototype.bind",p),E.registerPlugin=Rn.registerPlugin,E.deregisterPlugin=Rn.deregisterPlugin,E.plugin=(e,t)=>(o.warn("videojs.plugin() is deprecated; use videojs.registerPlugin() instead"),Rn.registerPlugin(e,t)),E.getPlugins=Rn.getPlugins,E.getPlugin=Rn.getPlugin,E.getPluginVersion=Rn.getPluginVersion,E.addLanguage=function(e,t){return e=(""+e).toLowerCase(),E.options.languages=d(E.options.languages,{[e]:t}),E.options.languages[e]},E.log=o,E.createLogger=W,E.time=t,E.createTimeRange=Nn(9,"videojs.createTimeRange","videojs.time.createTimeRanges",jt),E.createTimeRanges=Nn(9,"videojs.createTimeRanges","videojs.time.createTimeRanges",jt),E.formatTime=Nn(9,"videojs.formatTime","videojs.time.formatTime",Wt),E.setFormatTime=Nn(9,"videojs.setFormatTime","videojs.time.setFormatTime",zt),E.resetFormatTime=Nn(9,"videojs.resetFormatTime","videojs.time.resetFormatTime",$t),E.parseUrl=Nn(9,"videojs.parseUrl","videojs.url.parseUrl",gi),E.isCrossOrigin=Nn(9,"videojs.isCrossOrigin","videojs.url.isCrossOrigin",yi),E.EventTarget=wt,E.any=yt,E.on=mt,E.one=ft,E.off=c,E.trigger=gt,E.xhr=Pi,E.TrackList=si,E.TextTrack=Fi,E.TextTrackList=li,E.AudioTrack=qi,E.AudioTrackList=ni,E.VideoTrack=ji,E.VideoTrackList=oi,["isEl","isTextNode","createEl","hasClass","addClass","removeClass","toggleClass","setAttributes","getAttributes","emptyEl","appendContent","insertContent"].forEach(e=>{E[e]=function(){return o.warn(`videojs.${e}() is deprecated; use videojs.dom.${e}() instead`),et[e].apply(null,arguments)}}),E.computedStyle=Nn(9,"videojs.computedStyle","videojs.dom.computedStyle",Je),E.dom=et,E.fn=Tt,E.num=$i,E.str=Bt,E.url=vi,E.Error={NetworkBadStatus:"networkbadstatus",NetworkRequestFailed:"networkrequestfailed",NetworkRequestAborted:"networkrequestaborted",NetworkRequestTimeout:"networkrequesttimeout",NetworkBodyParserFailed:"networkbodyparserfailed",StreamingHlsPlaylistParserError:"streaminghlsplaylistparsererror",StreamingDashManifestParserError:"streamingdashmanifestparsererror",StreamingContentSteeringParserError:"streamingcontentsteeringparsererror",StreamingVttParserError:"streamingvttparsererror",StreamingFailedToSelectNextSegment:"streamingfailedtoselectnextsegment",StreamingFailedToDecryptSegment:"streamingfailedtodecryptsegment",StreamingFailedToTransmuxSegment:"streamingfailedtotransmuxsegment",StreamingFailedToAppendSegment:"streamingfailedtoappendsegment",StreamingCodecsChangeError:"streamingcodecschangeerror"},Ti(function(e,t){ +/*! @name videojs-contrib-quality-levels @version 4.1.0 @license Apache-2.0 */ +e.exports=function(e){function t(e){return e&&typeof e==="object"&&"default"in e?e:{default:e}}var i=t(e);class s{constructor(e){let t=this;t.id=e.id;t.label=t.id;t.width=e.width;t.height=e.height;t.bitrate=e.bandwidth;t.frameRate=e.frameRate;t.enabled_=e.enabled;Object.defineProperty(t,"enabled",{get(){return t.enabled_()},set(e){t.enabled_(e)}});return t}}class n extends i["default"].EventTarget{constructor(){super();let e=this;e.levels_=[];e.selectedIndex_=-1;Object.defineProperty(e,"selectedIndex",{get(){return e.selectedIndex_}});Object.defineProperty(e,"length",{get(){return e.levels_.length}});e[Symbol.iterator]=()=>e.levels_.values();return e}addQualityLevel(e){let t=this.getQualityLevelById(e.id);if(t)return t;const i=this.levels_.length;t=new s(e);if(!(""+i in this))Object.defineProperty(this,i,{get(){return this.levels_[i]}});this.levels_.push(t);this.trigger({qualityLevel:t,type:"addqualitylevel"});return t}removeQualityLevel(i){let s=null;for(let e=0,t=this.length;ee)this.selectedIndex_--;break}if(s)this.trigger({qualityLevel:i,type:"removequalitylevel"});return s}getQualityLevelById(i){for(let e=0,t=this.length;es;e.qualityLevels.VERSION=a;return s},o=function(e){return r(this,i["default"].obj.merge({},e))};return i["default"].registerPlugin("qualityLevels",o),o.VERSION=a,o}(E)});function Un(e){return window.atob?window.atob(e):Buffer.from(e,"base64").toString("binary")}var Bn="https://example.com",Fn=function(e,t){if(/^[a-z]+:/i.test(t))return t;/^data:/.test(e)&&(e=window.location&&window.location.href||"");var i=/^\/\//.test(e),s=!window.location&&!/\/\//i.test(e),t=(e=new window.URL(e,window.location||Bn),new URL(t,e));return s?t.href.slice(Bn.length):i?t.href.slice(t.protocol.length):t.href},Qr=function(){function e(){this.listeners={}}var t=e.prototype;return t.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)},t.off=function(e,t){return!!this.listeners[e]&&(t=this.listeners[e].indexOf(t),this.listeners[e]=this.listeners[e].slice(0),this.listeners[e].splice(t,1),-1{var e=e.split("x"),t={};return e[0]&&(t.width=parseInt(e[0],10)),e[1]&&(t.height=parseInt(e[1],10)),t};class Wn extends Qr{constructor(){super(),this.customParsers=[],this.tagMappers=[]}push(i){let a,o;0!==(i=i.trim()).length&&("#"!==i[0]?this.trigger("data",{type:"uri",uri:i}):this.tagMappers.reduce((e,t)=>{t=t(i);return t===i?e:e.concat([t])},[i]).forEach(t=>{for(let e=0;ee),this.customParsers.push(e=>{if(t.exec(e))return this.trigger("data",{type:"custom",data:s(e),customType:i,segment:r}),!0})}addTagMapper({expression:t,map:i}){this.tagMappers.push(e=>t.test(e)?i(e):e)}}function Gn(t){let i={};return Object.keys(t).forEach(function(e){i[e.toLowerCase().replace(/-(\w)/g,e=>e[1].toUpperCase())]=t[e]}),i}function Xn(e){var t,i,s,r,n,{serverControl:e,targetDuration:a,partTargetDuration:o}=e;e&&(t="#EXT-X-SERVER-CONTROL",i="holdBack",s="partHoldBack",r=a&&3*a,n=o&&2*o,a&&!e.hasOwnProperty(i)&&(e[i]=r,this.trigger("info",{message:t+` defaulting HOLD-BACK to targetDuration * 3 (${r}).`})),r&&e[i]{o.uri||!o.parts&&!o.preloadHints||(!o.map&&l&&(o.map=l),!o.key&&d&&(o.key=d),o.timeline||"number"!=typeof c||(o.timeline=c),this.manifest.preloadSegment=o)}),this.parseStream.on("data",function(n){let t,i;if(r.manifest.definitions)for(var e in r.manifest.definitions)if(n.uri&&(n.uri=n.uri.replace(`{$${e}}`,r.manifest.definitions[e])),n.attributes)for(var s in n.attributes)"string"==typeof n.attributes[s]&&(n.attributes[s]=n.attributes[s].replace(`{$${e}}`,r.manifest.definitions[e]));({tag(){({version(){n.version&&(this.manifest.version=n.version)},"allow-cache"(){this.manifest.allowCache=n.allowed,"allowed"in n||(this.trigger("info",{message:"defaulting allowCache to YES"}),this.manifest.allowCache=!0)},byterange(){var e={};"length"in n&&((o.byterange=e).length=n.length,"offset"in n||(n.offset=p)),"offset"in n&&((o.byterange=e).offset=n.offset),p=e.offset+e.length},endlist(){this.manifest.endList=!0},inf(){"mediaSequence"in this.manifest||(this.manifest.mediaSequence=0,this.trigger("info",{message:"defaulting media sequence to zero"})),"discontinuitySequence"in this.manifest||(this.manifest.discontinuitySequence=0,this.trigger("info",{message:"defaulting discontinuity sequence to zero"})),n.title&&(o.title=n.title),0(t.programDateTime=e-1e3*t.duration,t.programDateTime),this.lastProgramDateTime)},targetduration(){!isFinite(n.duration)||n.duration<0?this.trigger("warn",{message:"ignoring invalid target duration: "+n.duration}):(this.manifest.targetDuration=n.duration,Xn.call(this,this.manifest))},start(){!n.attributes||isNaN(n.attributes["TIME-OFFSET"])?this.trigger("warn",{message:"ignoring start declaration without appropriate attribute list"}):this.manifest.start={timeOffset:n.attributes["TIME-OFFSET"],precise:n.attributes.PRECISE}},"cue-out"(){o.cueOut=n.data},"cue-out-cont"(){o.cueOutCont=n.data},"cue-in"(){o.cueIn=n.data},skip(){this.manifest.skip=Gn(n.attributes),this.warnOnMissingAttributes_("#EXT-X-SKIP",n.attributes,["SKIPPED-SEGMENTS"])},part(){h=!0;var e=this.manifest.segments.length,t=Gn(n.attributes),t=(o.parts=o.parts||[],o.parts.push(t),t.byterange&&(t.byterange.hasOwnProperty("offset")||(t.byterange.offset=m),m=t.byterange.offset+t.byterange.length),o.parts.length-1);this.warnOnMissingAttributes_(`#EXT-X-PART #${t} for segment #`+e,n.attributes,["URI","DURATION"]),this.manifest.renditionReports&&this.manifest.renditionReports.forEach((e,t)=>{e.hasOwnProperty("lastPart")||this.trigger("warn",{message:`#EXT-X-RENDITION-REPORT #${t} lacks required attribute(s): LAST-PART`})})},"server-control"(){var e=this.manifest.serverControl=Gn(n.attributes);e.hasOwnProperty("canBlockReload")||(e.canBlockReload=!1,this.trigger("info",{message:"#EXT-X-SERVER-CONTROL defaulting CAN-BLOCK-RELOAD to false"})),Xn.call(this,this.manifest),e.canSkipDateranges&&!e.hasOwnProperty("canSkipUntil")&&this.trigger("warn",{message:"#EXT-X-SERVER-CONTROL lacks required attribute CAN-SKIP-UNTIL which is required when CAN-SKIP-DATERANGES is set"})},"preload-hint"(){var t=this.manifest.segments.length,i=Gn(n.attributes),e=i.type&&"PART"===i.type,s=(o.preloadHints=o.preloadHints||[],o.preloadHints.push(i),!i.byterange||i.byterange.hasOwnProperty("offset")||(i.byterange.offset=e?m:0,e&&(m=i.byterange.offset+i.byterange.length)),o.preloadHints.length-1);if(this.warnOnMissingAttributes_(`#EXT-X-PRELOAD-HINT #${s} for segment #`+t,n.attributes,["TYPE","URI"]),i.type)for(let e=0;ee.id===t.id);this.manifest.dateRanges[e]=f(this.manifest.dateRanges[e],t),g[t.id]=f(g[t.id],t),this.manifest.dateRanges.pop()}else g[t.id]=t},"independent-segments"(){this.manifest.independentSegments=!0},"i-frames-only"(){this.manifest.iFramesOnly=!0,this.requiredCompatibilityversion(this.manifest.version,4)},"content-steering"(){this.manifest.contentSteering=Gn(n.attributes),this.warnOnMissingAttributes_("#EXT-X-CONTENT-STEERING",n.attributes,["SERVER-URI"])},define(){this.manifest.definitions=this.manifest.definitions||{};var e,t=(e,t)=>{e in this.manifest.definitions?this.trigger("error",{message:"EXT-X-DEFINE: Duplicate name "+e}):this.manifest.definitions[e]=t};return"QUERYPARAM"in n.attributes?"NAME"in n.attributes||"IMPORT"in n.attributes?void this.trigger("error",{message:"EXT-X-DEFINE: Invalid attributes"}):(e=this.params.get(n.attributes.QUERYPARAM))?void t(n.attributes.QUERYPARAM,decodeURIComponent(e)):void this.trigger("error",{message:"EXT-X-DEFINE: No query param "+n.attributes.QUERYPARAM}):"NAME"in n.attributes?"IMPORT"in n.attributes?void this.trigger("error",{message:"EXT-X-DEFINE: Invalid attributes"}):"VALUE"in n.attributes&&"string"==typeof n.attributes.VALUE?void t(n.attributes.NAME,n.attributes.VALUE):void this.trigger("error",{message:"EXT-X-DEFINE: No value for "+n.attributes.NAME}):"IMPORT"in n.attributes?this.mainDefinitions[n.attributes.IMPORT]?void t(n.attributes.IMPORT,this.mainDefinitions[n.attributes.IMPORT]):void this.trigger("error",{message:`EXT-X-DEFINE: No value ${n.attributes.IMPORT} to import, or IMPORT used on main playlist`}):void this.trigger("error",{message:"EXT-X-DEFINE: No attribute"})},"i-frame-playlist"(){this.manifest.iFramePlaylists.push({attributes:n.attributes,uri:n.uri,timeline:c}),this.warnOnMissingAttributes_("#EXT-X-I-FRAME-STREAM-INF",n.attributes,["BANDWIDTH","URI"])}}[n.tagType]||function(){}).call(r)},uri(){o.uri=n.uri,a.push(o),!this.manifest.targetDuration||"duration"in o||(this.trigger("warn",{message:"defaulting segment duration to the target duration"}),o.duration=this.manifest.targetDuration),d&&(o.key=d),o.timeline=c,l&&(o.map=l),m=0,null!==this.lastProgramDateTime&&(o.programDateTime=this.lastProgramDateTime,this.lastProgramDateTime+=1e3*o.duration),o={}},comment(){},custom(){n.segment?(o.custom=o.custom||{},o.custom[n.customType]=n.data):(this.manifest.custom=this.manifest.custom||{},this.manifest.custom[n.customType]=n.data)}})[n.type].call(r)})}requiredCompatibilityversion(e,t){(e=e.length&&t.call(e,function(e,t){return e===(n[t]?n[t]&i[r+t]:i[r+t])})},_a=function(r,e,n){e.forEach(function(e){for(var t in r.mediaGroups[e])for(var i in r.mediaGroups[e][t]){var s=r.mediaGroups[e][t][i];n(s,e,t,i)}})};function va(e,t){return(t=void 0===t?Object:t)&&"function"==typeof t.freeze?t.freeze(e):e}var ba=va({HTML:"text/html",isHTML:function(e){return e===ba.HTML},XML_APPLICATION:"application/xml",XML_TEXT:"text/xml",XML_XHTML_APPLICATION:"application/xhtml+xml",XML_SVG_IMAGE:"image/svg+xml"}),Ta=va({HTML:"http://www.w3.org/1999/xhtml",isHTML:function(e){return e===Ta.HTML},SVG:"http://www.w3.org/2000/svg",XML:"http://www.w3.org/XML/1998/namespace",XMLNS:"http://www.w3.org/2000/xmlns/"}),Sa={assign:function(e,t){if(null===e||"object"!=typeof e)throw new TypeError("target is not an object");for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e},find:function(e,t,i){if(void 0===i&&(i=Array.prototype),e&&"function"==typeof i.find)return i.find.call(e,t);for(var s=0;s"==e&&">")||("&"==e?"&":'"'==e&&""")||"&#"+e.charCodeAt()+";"}function ja(e,t){if(t(e))return 1;if(e=e.firstChild)do{if(ja(e,t))return 1}while(e=e.nextSibling)}function Va(){this.ownerDocument=this}function Ha(e,t,i){e&&e._inc++,i.namespaceURI===Ea.XMLNS&&delete t._nsMap[i.prefix?i.localName:""]}function za(e,t,i){if(e&&e._inc){e._inc++;var s=t.childNodes;if(i)s[s.length++]=i;else{for(var r=t.firstChild,n=0;r;)r=(s[n++]=r).nextSibling;s.length=n,delete s[s.length]}}}function $a(e,t){var i=t.previousSibling,s=t.nextSibling;return i?i.nextSibling=s:e.firstChild=s,s?s.previousSibling=i:e.lastChild=i,t.parentNode=null,t.previousSibling=null,t.nextSibling=null,za(e.ownerDocument,e),t}function Wa(e){return e&&e.nodeType===x.DOCUMENT_TYPE_NODE}function Ga(e){return e&&e.nodeType===x.ELEMENT_NODE}function Xa(e){return e&&e.nodeType===x.TEXT_NODE}function Ka(e,t){var i,e=e.childNodes||[];if(!wa(e,Ga)&&!Wa(t))return i=wa(e,Wa),!(t&&i&&e.indexOf(i)>e.indexOf(t))}function Ya(e,t){var i,e=e.childNodes||[];if(!wa(e,function(e){return Ga(e)&&e!==t}))return i=wa(e,Wa),!(t&&i&&e.indexOf(i)>e.indexOf(t))}function Qa(e,t,i){if(!(s=e)||s.nodeType!==x.DOCUMENT_NODE&&s.nodeType!==x.DOCUMENT_FRAGMENT_NODE&&s.nodeType!==x.ELEMENT_NODE)throw new I(Da,"Unexpected parent node type "+e.nodeType);var s;if(i&&i.parentNode!==e)throw new I(Pa,"child not in parent");if(!(s=t)||!(Ga(s)||Xa(s)||Wa(s)||s.nodeType===x.DOCUMENT_FRAGMENT_NODE||s.nodeType===x.COMMENT_NODE||s.nodeType===x.PROCESSING_INSTRUCTION_NODE)||Wa(t)&&e.nodeType!==x.DOCUMENT_NODE)throw new I(Da,"Unexpected node type "+t.nodeType+" for parent node type "+e.nodeType)}function Ja(e,t,i){var s=e.childNodes||[],r=t.childNodes||[];if(t.nodeType===x.DOCUMENT_FRAGMENT_NODE){var n=r.filter(Ga);if(1"),i&&/^script$/i.test(l))for(;o;)o.data?t.push(o.data):_o(o,t,i,s,r.slice()),o=o.nextSibling;else for(;o;)_o(o,t,i,s,r.slice()),o=o.nextSibling;t.push("")}else t.push("/>");return;case 9:case 11:for(o=e.firstChild;o;)_o(o,t,i,s,r.slice()),o=o.nextSibling;return;case 2:return yo(t,e.name,e.value);case 3:return t.push(e.data.replace(/[<&>]/g,qa));case 4:return t.push("");case 8:return t.push("\x3c!--",e.data,"--\x3e");case 10:var _=e.publicId,v=e.systemId;return t.push("")):v&&"."!=v?t.push(" SYSTEM ",v,">"):((_=e.internalSubset)&&t.push(" [",_,"]"),t.push(">")));case 7:return t.push("");case 5:return t.push("&",e.nodeName,";");default:t.push("??",e.nodeName)}}function vo(e,t,i){e[t]=i}r.INVALID_STATE_ERR=(k[11]="Invalid state",11),r.SYNTAX_ERR=(k[12]="Syntax error",12),r.INVALID_MODIFICATION_ERR=(k[13]="Invalid modification",13),r.NAMESPACE_ERR=(k[14]="Invalid namespace",14),r.INVALID_ACCESS_ERR=(k[15]="Invalid access",15),I.prototype=Error.prototype,xa(r,I),La.prototype={length:0,item:function(e){return 0<=e&&e",lt:"<",quot:'"'}),t.HTML_ENTITIES=i({Aacute:"Á",aacute:"á",Abreve:"Ă",abreve:"ă",ac:"∾",acd:"∿",acE:"∾̳",Acirc:"Â",acirc:"â",acute:"´",Acy:"А",acy:"а",AElig:"Æ",aelig:"æ",af:"⁡",Afr:"𝔄",afr:"𝔞",Agrave:"À",agrave:"à",alefsym:"ℵ",aleph:"ℵ",Alpha:"Α",alpha:"α",Amacr:"Ā",amacr:"ā",amalg:"⨿",AMP:"&",amp:"&",And:"⩓",and:"∧",andand:"⩕",andd:"⩜",andslope:"⩘",andv:"⩚",ang:"∠",ange:"⦤",angle:"∠",angmsd:"∡",angmsdaa:"⦨",angmsdab:"⦩",angmsdac:"⦪",angmsdad:"⦫",angmsdae:"⦬",angmsdaf:"⦭",angmsdag:"⦮",angmsdah:"⦯",angrt:"∟",angrtvb:"⊾",angrtvbd:"⦝",angsph:"∢",angst:"Å",angzarr:"⍼",Aogon:"Ą",aogon:"ą",Aopf:"𝔸",aopf:"𝕒",ap:"≈",apacir:"⩯",apE:"⩰",ape:"≊",apid:"≋",apos:"'",ApplyFunction:"⁡",approx:"≈",approxeq:"≊",Aring:"Å",aring:"å",Ascr:"𝒜",ascr:"𝒶",Assign:"≔",ast:"*",asymp:"≈",asympeq:"≍",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",awconint:"∳",awint:"⨑",backcong:"≌",backepsilon:"϶",backprime:"‵",backsim:"∽",backsimeq:"⋍",Backslash:"∖",Barv:"⫧",barvee:"⊽",Barwed:"⌆",barwed:"⌅",barwedge:"⌅",bbrk:"⎵",bbrktbrk:"⎶",bcong:"≌",Bcy:"Б",bcy:"б",bdquo:"„",becaus:"∵",Because:"∵",because:"∵",bemptyv:"⦰",bepsi:"϶",bernou:"ℬ",Bernoullis:"ℬ",Beta:"Β",beta:"β",beth:"ℶ",between:"≬",Bfr:"𝔅",bfr:"𝔟",bigcap:"⋂",bigcirc:"◯",bigcup:"⋃",bigodot:"⨀",bigoplus:"⨁",bigotimes:"⨂",bigsqcup:"⨆",bigstar:"★",bigtriangledown:"▽",bigtriangleup:"△",biguplus:"⨄",bigvee:"⋁",bigwedge:"⋀",bkarow:"⤍",blacklozenge:"⧫",blacksquare:"▪",blacktriangle:"▴",blacktriangledown:"▾",blacktriangleleft:"◂",blacktriangleright:"▸",blank:"␣",blk12:"▒",blk14:"░",blk34:"▓",block:"█",bne:"=⃥",bnequiv:"≡⃥",bNot:"⫭",bnot:"⌐",Bopf:"𝔹",bopf:"𝕓",bot:"⊥",bottom:"⊥",bowtie:"⋈",boxbox:"⧉",boxDL:"╗",boxDl:"╖",boxdL:"╕",boxdl:"┐",boxDR:"╔",boxDr:"╓",boxdR:"╒",boxdr:"┌",boxH:"═",boxh:"─",boxHD:"╦",boxHd:"╤",boxhD:"╥",boxhd:"┬",boxHU:"╩",boxHu:"╧",boxhU:"╨",boxhu:"┴",boxminus:"⊟",boxplus:"⊞",boxtimes:"⊠",boxUL:"╝",boxUl:"╜",boxuL:"╛",boxul:"┘",boxUR:"╚",boxUr:"╙",boxuR:"╘",boxur:"└",boxV:"║",boxv:"│",boxVH:"╬",boxVh:"╫",boxvH:"╪",boxvh:"┼",boxVL:"╣",boxVl:"╢",boxvL:"╡",boxvl:"┤",boxVR:"╠",boxVr:"╟",boxvR:"╞",boxvr:"├",bprime:"‵",Breve:"˘",breve:"˘",brvbar:"¦",Bscr:"ℬ",bscr:"𝒷",bsemi:"⁏",bsim:"∽",bsime:"⋍",bsol:"\\",bsolb:"⧅",bsolhsub:"⟈",bull:"•",bullet:"•",bump:"≎",bumpE:"⪮",bumpe:"≏",Bumpeq:"≎",bumpeq:"≏",Cacute:"Ć",cacute:"ć",Cap:"⋒",cap:"∩",capand:"⩄",capbrcup:"⩉",capcap:"⩋",capcup:"⩇",capdot:"⩀",CapitalDifferentialD:"ⅅ",caps:"∩︀",caret:"⁁",caron:"ˇ",Cayleys:"ℭ",ccaps:"⩍",Ccaron:"Č",ccaron:"č",Ccedil:"Ç",ccedil:"ç",Ccirc:"Ĉ",ccirc:"ĉ",Cconint:"∰",ccups:"⩌",ccupssm:"⩐",Cdot:"Ċ",cdot:"ċ",cedil:"¸",Cedilla:"¸",cemptyv:"⦲",cent:"¢",CenterDot:"·",centerdot:"·",Cfr:"ℭ",cfr:"𝔠",CHcy:"Ч",chcy:"ч",check:"✓",checkmark:"✓",Chi:"Χ",chi:"χ",cir:"○",circ:"ˆ",circeq:"≗",circlearrowleft:"↺",circlearrowright:"↻",circledast:"⊛",circledcirc:"⊚",circleddash:"⊝",CircleDot:"⊙",circledR:"®",circledS:"Ⓢ",CircleMinus:"⊖",CirclePlus:"⊕",CircleTimes:"⊗",cirE:"⧃",cire:"≗",cirfnint:"⨐",cirmid:"⫯",cirscir:"⧂",ClockwiseContourIntegral:"∲",CloseCurlyDoubleQuote:"”",CloseCurlyQuote:"’",clubs:"♣",clubsuit:"♣",Colon:"∷",colon:":",Colone:"⩴",colone:"≔",coloneq:"≔",comma:",",commat:"@",comp:"∁",compfn:"∘",complement:"∁",complexes:"ℂ",cong:"≅",congdot:"⩭",Congruent:"≡",Conint:"∯",conint:"∮",ContourIntegral:"∮",Copf:"ℂ",copf:"𝕔",coprod:"∐",Coproduct:"∐",COPY:"©",copy:"©",copysr:"℗",CounterClockwiseContourIntegral:"∳",crarr:"↵",Cross:"⨯",cross:"✗",Cscr:"𝒞",cscr:"𝒸",csub:"⫏",csube:"⫑",csup:"⫐",csupe:"⫒",ctdot:"⋯",cudarrl:"⤸",cudarrr:"⤵",cuepr:"⋞",cuesc:"⋟",cularr:"↶",cularrp:"⤽",Cup:"⋓",cup:"∪",cupbrcap:"⩈",CupCap:"≍",cupcap:"⩆",cupcup:"⩊",cupdot:"⊍",cupor:"⩅",cups:"∪︀",curarr:"↷",curarrm:"⤼",curlyeqprec:"⋞",curlyeqsucc:"⋟",curlyvee:"⋎",curlywedge:"⋏",curren:"¤",curvearrowleft:"↶",curvearrowright:"↷",cuvee:"⋎",cuwed:"⋏",cwconint:"∲",cwint:"∱",cylcty:"⌭",Dagger:"‡",dagger:"†",daleth:"ℸ",Darr:"↡",dArr:"⇓",darr:"↓",dash:"‐",Dashv:"⫤",dashv:"⊣",dbkarow:"⤏",dblac:"˝",Dcaron:"Ď",dcaron:"ď",Dcy:"Д",dcy:"д",DD:"ⅅ",dd:"ⅆ",ddagger:"‡",ddarr:"⇊",DDotrahd:"⤑",ddotseq:"⩷",deg:"°",Del:"∇",Delta:"Δ",delta:"δ",demptyv:"⦱",dfisht:"⥿",Dfr:"𝔇",dfr:"𝔡",dHar:"⥥",dharl:"⇃",dharr:"⇂",DiacriticalAcute:"´",DiacriticalDot:"˙",DiacriticalDoubleAcute:"˝",DiacriticalGrave:"`",DiacriticalTilde:"˜",diam:"⋄",Diamond:"⋄",diamond:"⋄",diamondsuit:"♦",diams:"♦",die:"¨",DifferentialD:"ⅆ",digamma:"ϝ",disin:"⋲",div:"÷",divide:"÷",divideontimes:"⋇",divonx:"⋇",DJcy:"Ђ",djcy:"ђ",dlcorn:"⌞",dlcrop:"⌍",dollar:"$",Dopf:"𝔻",dopf:"𝕕",Dot:"¨",dot:"˙",DotDot:"⃜",doteq:"≐",doteqdot:"≑",DotEqual:"≐",dotminus:"∸",dotplus:"∔",dotsquare:"⊡",doublebarwedge:"⌆",DoubleContourIntegral:"∯",DoubleDot:"¨",DoubleDownArrow:"⇓",DoubleLeftArrow:"⇐",DoubleLeftRightArrow:"⇔",DoubleLeftTee:"⫤",DoubleLongLeftArrow:"⟸",DoubleLongLeftRightArrow:"⟺",DoubleLongRightArrow:"⟹",DoubleRightArrow:"⇒",DoubleRightTee:"⊨",DoubleUpArrow:"⇑",DoubleUpDownArrow:"⇕",DoubleVerticalBar:"∥",DownArrow:"↓",Downarrow:"⇓",downarrow:"↓",DownArrowBar:"⤓",DownArrowUpArrow:"⇵",DownBreve:"̑",downdownarrows:"⇊",downharpoonleft:"⇃",downharpoonright:"⇂",DownLeftRightVector:"⥐",DownLeftTeeVector:"⥞",DownLeftVector:"↽",DownLeftVectorBar:"⥖",DownRightTeeVector:"⥟",DownRightVector:"⇁",DownRightVectorBar:"⥗",DownTee:"⊤",DownTeeArrow:"↧",drbkarow:"⤐",drcorn:"⌟",drcrop:"⌌",Dscr:"𝒟",dscr:"𝒹",DScy:"Ѕ",dscy:"ѕ",dsol:"⧶",Dstrok:"Đ",dstrok:"đ",dtdot:"⋱",dtri:"▿",dtrif:"▾",duarr:"⇵",duhar:"⥯",dwangle:"⦦",DZcy:"Џ",dzcy:"џ",dzigrarr:"⟿",Eacute:"É",eacute:"é",easter:"⩮",Ecaron:"Ě",ecaron:"ě",ecir:"≖",Ecirc:"Ê",ecirc:"ê",ecolon:"≕",Ecy:"Э",ecy:"э",eDDot:"⩷",Edot:"Ė",eDot:"≑",edot:"ė",ee:"ⅇ",efDot:"≒",Efr:"𝔈",efr:"𝔢",eg:"⪚",Egrave:"È",egrave:"è",egs:"⪖",egsdot:"⪘",el:"⪙",Element:"∈",elinters:"⏧",ell:"ℓ",els:"⪕",elsdot:"⪗",Emacr:"Ē",emacr:"ē",empty:"∅",emptyset:"∅",EmptySmallSquare:"◻",emptyv:"∅",EmptyVerySmallSquare:"▫",emsp:" ",emsp13:" ",emsp14:" ",ENG:"Ŋ",eng:"ŋ",ensp:" ",Eogon:"Ę",eogon:"ę",Eopf:"𝔼",eopf:"𝕖",epar:"⋕",eparsl:"⧣",eplus:"⩱",epsi:"ε",Epsilon:"Ε",epsilon:"ε",epsiv:"ϵ",eqcirc:"≖",eqcolon:"≕",eqsim:"≂",eqslantgtr:"⪖",eqslantless:"⪕",Equal:"⩵",equals:"=",EqualTilde:"≂",equest:"≟",Equilibrium:"⇌",equiv:"≡",equivDD:"⩸",eqvparsl:"⧥",erarr:"⥱",erDot:"≓",Escr:"ℰ",escr:"ℯ",esdot:"≐",Esim:"⩳",esim:"≂",Eta:"Η",eta:"η",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",excl:"!",exist:"∃",Exists:"∃",expectation:"ℰ",ExponentialE:"ⅇ",exponentiale:"ⅇ",fallingdotseq:"≒",Fcy:"Ф",fcy:"ф",female:"♀",ffilig:"ffi",fflig:"ff",ffllig:"ffl",Ffr:"𝔉",ffr:"𝔣",filig:"fi",FilledSmallSquare:"◼",FilledVerySmallSquare:"▪",fjlig:"fj",flat:"♭",fllig:"fl",fltns:"▱",fnof:"ƒ",Fopf:"𝔽",fopf:"𝕗",ForAll:"∀",forall:"∀",fork:"⋔",forkv:"⫙",Fouriertrf:"ℱ",fpartint:"⨍",frac12:"½",frac13:"⅓",frac14:"¼",frac15:"⅕",frac16:"⅙",frac18:"⅛",frac23:"⅔",frac25:"⅖",frac34:"¾",frac35:"⅗",frac38:"⅜",frac45:"⅘",frac56:"⅚",frac58:"⅝",frac78:"⅞",frasl:"⁄",frown:"⌢",Fscr:"ℱ",fscr:"𝒻",gacute:"ǵ",Gamma:"Γ",gamma:"γ",Gammad:"Ϝ",gammad:"ϝ",gap:"⪆",Gbreve:"Ğ",gbreve:"ğ",Gcedil:"Ģ",Gcirc:"Ĝ",gcirc:"ĝ",Gcy:"Г",gcy:"г",Gdot:"Ġ",gdot:"ġ",gE:"≧",ge:"≥",gEl:"⪌",gel:"⋛",geq:"≥",geqq:"≧",geqslant:"⩾",ges:"⩾",gescc:"⪩",gesdot:"⪀",gesdoto:"⪂",gesdotol:"⪄",gesl:"⋛︀",gesles:"⪔",Gfr:"𝔊",gfr:"𝔤",Gg:"⋙",gg:"≫",ggg:"⋙",gimel:"ℷ",GJcy:"Ѓ",gjcy:"ѓ",gl:"≷",gla:"⪥",glE:"⪒",glj:"⪤",gnap:"⪊",gnapprox:"⪊",gnE:"≩",gne:"⪈",gneq:"⪈",gneqq:"≩",gnsim:"⋧",Gopf:"𝔾",gopf:"𝕘",grave:"`",GreaterEqual:"≥",GreaterEqualLess:"⋛",GreaterFullEqual:"≧",GreaterGreater:"⪢",GreaterLess:"≷",GreaterSlantEqual:"⩾",GreaterTilde:"≳",Gscr:"𝒢",gscr:"ℊ",gsim:"≳",gsime:"⪎",gsiml:"⪐",Gt:"≫",GT:">",gt:">",gtcc:"⪧",gtcir:"⩺",gtdot:"⋗",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"⋗",gtreqless:"⋛",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"ℋ",HARDcy:"Ъ",hardcy:"ъ",hArr:"⇔",harr:"↔",harrcir:"⥈",harrw:"↭",Hat:"^",hbar:"ℏ",Hcirc:"Ĥ",hcirc:"ĥ",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",Hfr:"ℌ",hfr:"𝔥",HilbertSpace:"ℋ",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",Hopf:"ℍ",hopf:"𝕙",horbar:"―",HorizontalLine:"─",Hscr:"ℋ",hscr:"𝒽",hslash:"ℏ",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"≏",hybull:"⁃",hyphen:"‐",Iacute:"Í",iacute:"í",ic:"⁣",Icirc:"Î",icirc:"î",Icy:"И",icy:"и",Idot:"İ",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",Ifr:"ℑ",ifr:"𝔦",Igrave:"Ì",igrave:"ì",ii:"ⅈ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"℩",IJlig:"IJ",ijlig:"ij",Im:"ℑ",Imacr:"Ī",imacr:"ī",image:"ℑ",ImaginaryI:"ⅈ",imagline:"ℐ",imagpart:"ℑ",imath:"ı",imof:"⊷",imped:"Ƶ",Implies:"⇒",in:"∈",incare:"℅",infin:"∞",infintie:"⧝",inodot:"ı",Int:"∬",int:"∫",intcal:"⊺",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"⋂",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"⁣",InvisibleTimes:"⁢",IOcy:"Ё",iocy:"ё",Iogon:"Į",iogon:"į",Iopf:"𝕀",iopf:"𝕚",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",Iscr:"ℐ",iscr:"𝒾",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"⋴",isinsv:"⋳",isinv:"∈",it:"⁢",Itilde:"Ĩ",itilde:"ĩ",Iukcy:"І",iukcy:"і",Iuml:"Ï",iuml:"ï",Jcirc:"Ĵ",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"𝔍",jfr:"𝔧",jmath:"ȷ",Jopf:"𝕁",jopf:"𝕛",Jscr:"𝒥",jscr:"𝒿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"є",Kappa:"Κ",kappa:"κ",kappav:"ϰ",Kcedil:"Ķ",kcedil:"ķ",Kcy:"К",kcy:"к",Kfr:"𝔎",kfr:"𝔨",kgreen:"ĸ",KHcy:"Х",khcy:"х",KJcy:"Ќ",kjcy:"ќ",Kopf:"𝕂",kopf:"𝕜",Kscr:"𝒦",kscr:"𝓀",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"ℒ",Lambda:"Λ",lambda:"λ",Lang:"⟪",lang:"⟨",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"ℒ",laquo:"«",Larr:"↞",lArr:"⇐",larr:"←",larrb:"⇤",larrbfs:"⤟",larrfs:"⤝",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",lat:"⪫",lAtail:"⤛",latail:"⤙",late:"⪭",lates:"⪭︀",lBarr:"⤎",lbarr:"⤌",lbbrk:"❲",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"⦏",lbrkslu:"⦍",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ļ",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",lE:"≦",le:"≤",LeftAngleBracket:"⟨",LeftArrow:"←",Leftarrow:"⇐",leftarrow:"←",LeftArrowBar:"⇤",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVector:"⇃",LeftDownVectorBar:"⥙",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrow:"↔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTee:"⊣",LeftTeeArrow:"↤",LeftTeeVector:"⥚",leftthreetimes:"⋋",LeftTriangle:"⊲",LeftTriangleBar:"⧏",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVector:"↿",LeftUpVectorBar:"⥘",LeftVector:"↼",LeftVectorBar:"⥒",lEg:"⪋",leg:"⋚",leq:"≤",leqq:"≦",leqslant:"⩽",les:"⩽",lescc:"⪨",lesdot:"⩿",lesdoto:"⪁",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"⋖",lesseqgtr:"⋚",lesseqqgtr:"⪋",LessEqualGreater:"⋚",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"𝔏",lfr:"𝔩",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"▄",LJcy:"Љ",ljcy:"љ",Ll:"⋘",ll:"≪",llarr:"⇇",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"◺",Lmidot:"Ŀ",lmidot:"ŀ",lmoust:"⎰",lmoustache:"⎰",lnap:"⪉",lnapprox:"⪉",lnE:"≨",lne:"⪇",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftarrow:"⟵",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longleftrightarrow:"⟷",longmapsto:"⟼",LongRightArrow:"⟶",Longrightarrow:"⟹",longrightarrow:"⟶",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"𝕃",lopf:"𝕝",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"◊",lozenge:"◊",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"‎",lrtri:"⊿",lsaquo:"‹",Lscr:"ℒ",lscr:"𝓁",Lsh:"↰",lsh:"↰",lsim:"≲",lsime:"⪍",lsimg:"⪏",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Ł",lstrok:"ł",Lt:"≪",LT:"<",lt:"<",ltcc:"⪦",ltcir:"⩹",ltdot:"⋖",lthree:"⋋",ltimes:"⋉",ltlarr:"⥶",ltquest:"⩻",ltri:"◃",ltrie:"⊴",ltrif:"◂",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"▮",mcomma:"⨩",Mcy:"М",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:" ",Mellintrf:"ℳ",Mfr:"𝔐",mfr:"𝔪",mho:"℧",micro:"µ",mid:"∣",midast:"*",midcir:"⫰",middot:"·",minus:"−",minusb:"⊟",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"⫛",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"𝕄",mopf:"𝕞",mp:"∓",Mscr:"ℳ",mscr:"𝓂",mstpos:"∾",Mu:"Μ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"ń",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natur:"♮",natural:"♮",naturals:"ℕ",nbsp:" ",nbump:"≎̸",nbumpe:"≏̸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Ņ",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"⩂",Ncy:"Н",ncy:"н",ndash:"–",ne:"≠",nearhk:"⤤",neArr:"⇗",nearr:"↗",nearrow:"↗",nedot:"≐̸",NegativeMediumSpace:"​",NegativeThickSpace:"​",NegativeThinSpace:"​",NegativeVeryThinSpace:"​",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"𝔑",nfr:"𝔫",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nhArr:"⇎",nharr:"↮",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"њ",nlArr:"⇍",nlarr:"↚",nldr:"‥",nlE:"≦̸",nle:"≰",nLeftarrow:"⇍",nleftarrow:"↚",nLeftrightarrow:"⇎",nleftrightarrow:"↮",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"⁠",NonBreakingSpace:" ",Nopf:"ℕ",nopf:"𝕟",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"≏̸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"⋷",notinvc:"⋶",NotLeftTriangle:"⋪",NotLeftTriangleBar:"⧏̸",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"⋠",NotReverseElement:"∌",NotRightTriangle:"⋫",NotRightTriangleBar:"⧐̸",NotRightTriangleEqual:"⋭",NotSquareSubset:"⊏̸",NotSquareSubsetEqual:"⋢",NotSquareSuperset:"⊐̸",NotSquareSupersetEqual:"⋣",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"⊁",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"⋡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"≁",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",npar:"∦",nparallel:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"⋠",npre:"⪯̸",nprec:"⊀",npreceq:"⪯̸",nrArr:"⇏",nrarr:"↛",nrarrc:"⤳̸",nrarrw:"↝̸",nRightarrow:"⇏",nrightarrow:"↛",nrtri:"⋫",nrtrie:"⋭",nsc:"⊁",nsccue:"⋡",nsce:"⪰̸",Nscr:"𝒩",nscr:"𝓃",nshortmid:"∤",nshortparallel:"∦",nsim:"≁",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"⋢",nsqsupe:"⋣",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"⊁",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"⋫",ntrianglerighteq:"⋭",Nu:"Ν",nu:"ν",num:"#",numero:"№",numsp:" ",nvap:"≍⃒",nVDash:"⊯",nVdash:"⊮",nvDash:"⊭",nvdash:"⊬",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwArr:"⇖",nwarr:"↖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",ocir:"⊚",Ocirc:"Ô",ocirc:"ô",Ocy:"О",ocy:"о",odash:"⊝",Odblac:"Ő",odblac:"ő",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Œ",oelig:"œ",ofcir:"⦿",Ofr:"𝔒",ofr:"𝔬",ogon:"˛",Ograve:"Ò",ograve:"ò",ogt:"⧁",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"Ō",omacr:"ō",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"𝕆",oopf:"𝕠",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",Or:"⩔",or:"∨",orarr:"↻",ord:"⩝",order:"ℴ",orderof:"ℴ",ordf:"ª",ordm:"º",origof:"⊶",oror:"⩖",orslope:"⩗",orv:"⩛",oS:"Ⓢ",Oscr:"𝒪",oscr:"ℴ",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",Otimes:"⨷",otimes:"⊗",otimesas:"⨶",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"⏞",OverBracket:"⎴",OverParenthesis:"⏜",par:"∥",para:"¶",parallel:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"𝔓",pfr:"𝔭",Phi:"Φ",phi:"φ",phiv:"ϕ",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"π",pitchfork:"⋔",piv:"ϖ",planck:"ℏ",planckh:"ℎ",plankv:"ℏ",plus:"+",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"ℌ",pointint:"⨕",Popf:"ℙ",popf:"𝕡",pound:"£",Pr:"⪻",pr:"≺",prap:"⪷",prcue:"≼",prE:"⪳",pre:"⪯",prec:"≺",precapprox:"⪷",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",precsim:"≾",Prime:"″",prime:"′",primes:"ℙ",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"∏",Product:"∏",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"∝",Proportion:"∷",Proportional:"∝",propto:"∝",prsim:"≾",prurel:"⊰",Pscr:"𝒫",pscr:"𝓅",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"𝔔",qfr:"𝔮",qint:"⨌",Qopf:"ℚ",qopf:"𝕢",qprime:"⁗",Qscr:"𝒬",qscr:"𝓆",quaternions:"ℍ",quatint:"⨖",quest:"?",questeq:"≟",QUOT:'"',quot:'"',rAarr:"⇛",race:"∽̱",Racute:"Ŕ",racute:"ŕ",radic:"√",raemptyv:"⦳",Rang:"⟫",rang:"⟩",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",Rarr:"↠",rArr:"⇒",rarr:"→",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"↝",rAtail:"⤜",ratail:"⤚",ratio:"∶",rationals:"ℚ",RBarr:"⤐",rBarr:"⤏",rbarr:"⤍",rbbrk:"❳",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"⦐",Rcaron:"Ř",rcaron:"ř",Rcedil:"Ŗ",rcedil:"ŗ",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"р",rdca:"⤷",rdldhar:"⥩",rdquo:"”",rdquor:"”",rdsh:"↳",Re:"ℜ",real:"ℜ",realine:"ℛ",realpart:"ℜ",reals:"ℝ",rect:"▭",REG:"®",reg:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",Rfr:"ℜ",rfr:"𝔯",rHar:"⥤",rhard:"⇁",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"ρ",rhov:"ϱ",RightAngleBracket:"⟩",RightArrow:"→",Rightarrow:"⇒",rightarrow:"→",RightArrowBar:"⇥",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"⥝",RightDownVector:"⇂",RightDownVectorBar:"⥕",RightFloor:"⌋",rightharpoondown:"⇁",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"↝",RightTee:"⊢",RightTeeArrow:"↦",RightTeeVector:"⥛",rightthreetimes:"⋌",RightTriangle:"⊳",RightTriangleBar:"⧐",RightTriangleEqual:"⊵",RightUpDownVector:"⥏",RightUpTeeVector:"⥜",RightUpVector:"↾",RightUpVectorBar:"⥔",RightVector:"⇀",RightVectorBar:"⥓",ring:"˚",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"‏",rmoust:"⎱",rmoustache:"⎱",rnmid:"⫮",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",Ropf:"ℝ",ropf:"𝕣",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",Rscr:"ℛ",rscr:"𝓇",Rsh:"↱",rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"⋌",rtimes:"⋊",rtri:"▹",rtrie:"⊵",rtrif:"▸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"℞",Sacute:"Ś",sacute:"ś",sbquo:"‚",Sc:"⪼",sc:"≻",scap:"⪸",Scaron:"Š",scaron:"š",sccue:"≽",scE:"⪴",sce:"⪰",Scedil:"Ş",scedil:"ş",Scirc:"Ŝ",scirc:"ŝ",scnap:"⪺",scnE:"⪶",scnsim:"⋩",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"с",sdot:"⋅",sdotb:"⊡",sdote:"⩦",searhk:"⤥",seArr:"⇘",searr:"↘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"𝔖",sfr:"𝔰",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"←",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"­",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sigmav:"ς",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"⪝",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"←",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ь",sol:"/",solb:"⧄",solbar:"⌿",Sopf:"𝕊",sopf:"𝕤",spades:"♠",spadesuit:"♠",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"⊏",sqsube:"⊑",sqsubset:"⊏",sqsubseteq:"⊑",sqsup:"⊐",sqsupe:"⊒",sqsupset:"⊐",sqsupseteq:"⊒",squ:"□",Square:"□",square:"□",SquareIntersection:"⊓",SquareSubset:"⊏",SquareSubsetEqual:"⊑",SquareSuperset:"⊐",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"▪",squf:"▪",srarr:"→",Sscr:"𝒮",sscr:"𝓈",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"ϕ",strns:"¯",Sub:"⋐",sub:"⊂",subdot:"⪽",subE:"⫅",sube:"⊆",subedot:"⫃",submult:"⫁",subnE:"⫋",subne:"⊊",subplus:"⪿",subrarr:"⥹",Subset:"⋐",subset:"⊂",subseteq:"⊆",subseteqq:"⫅",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"⫋",subsim:"⫇",subsub:"⫕",subsup:"⫓",succ:"≻",succapprox:"⪸",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"⋩",succsim:"≿",SuchThat:"∋",Sum:"∑",sum:"∑",sung:"♪",Sup:"⋑",sup:"⊃",sup1:"¹",sup2:"²",sup3:"³",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"⫄",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"⫗",suplarr:"⥻",supmult:"⫂",supnE:"⫌",supne:"⊋",supplus:"⫀",Supset:"⋑",supset:"⊃",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"⫌",supsim:"⫈",supsub:"⫔",supsup:"⫖",swarhk:"⤦",swArr:"⇙",swarr:"↙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:"\t",target:"⌖",Tau:"Τ",tau:"τ",tbrk:"⎴",Tcaron:"Ť",tcaron:"ť",Tcedil:"Ţ",tcedil:"ţ",Tcy:"Т",tcy:"т",tdot:"⃛",telrec:"⌕",Tfr:"𝔗",tfr:"𝔱",there4:"∴",Therefore:"∴",therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thetav:"ϑ",thickapprox:"≈",thicksim:"∼",ThickSpace:"  ",thinsp:" ",ThinSpace:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",Tilde:"∼",tilde:"˜",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",times:"×",timesb:"⊠",timesbar:"⨱",timesd:"⨰",tint:"∭",toea:"⤨",top:"⊤",topbot:"⌶",topcir:"⫱",Topf:"𝕋",topf:"𝕥",topfork:"⫚",tosa:"⤩",tprime:"‴",TRADE:"™",trade:"™",triangle:"▵",triangledown:"▿",triangleleft:"◃",trianglelefteq:"⊴",triangleq:"≜",triangleright:"▹",trianglerighteq:"⊵",tridot:"◬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"⧍",tritime:"⨻",trpezium:"⏢",Tscr:"𝒯",tscr:"𝓉",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"ћ",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",Uarr:"↟",uArr:"⇑",uarr:"↑",Uarrocir:"⥉",Ubrcy:"Ў",ubrcy:"ў",Ubreve:"Ŭ",ubreve:"ŭ",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Ű",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"𝔘",ufr:"𝔲",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"▀",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"⌏",ultri:"◸",Umacr:"Ū",umacr:"ū",uml:"¨",UnderBar:"_",UnderBrace:"⏟",UnderBracket:"⎵",UnderParenthesis:"⏝",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"𝕌",uopf:"𝕦",UpArrow:"↑",Uparrow:"⇑",uparrow:"↑",UpArrowBar:"⤒",UpArrowDownArrow:"⇅",UpDownArrow:"↕",Updownarrow:"⇕",updownarrow:"↕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",Upsi:"ϒ",upsi:"υ",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",UpTee:"⊥",UpTeeArrow:"↥",upuparrows:"⇈",urcorn:"⌝",urcorner:"⌝",urcrop:"⌎",Uring:"Ů",uring:"ů",urtri:"◹",Uscr:"𝒰",uscr:"𝓊",utdot:"⋰",Utilde:"Ũ",utilde:"ũ",utri:"▵",utrif:"▴",uuarr:"⇈",Uuml:"Ü",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"ϰ",varnothing:"∅",varphi:"ϕ",varpi:"ϖ",varpropto:"∝",vArr:"⇕",varr:"↕",varrho:"ϱ",varsigma:"ς",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"ϑ",vartriangleleft:"⊲",vartriangleright:"⊳",Vbar:"⫫",vBar:"⫨",vBarv:"⫩",Vcy:"В",vcy:"в",VDash:"⊫",Vdash:"⊩",vDash:"⊨",vdash:"⊢",Vdashl:"⫦",Vee:"⋁",vee:"∨",veebar:"⊻",veeeq:"≚",vellip:"⋮",Verbar:"‖",verbar:"|",Vert:"‖",vert:"|",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"❘",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"𝔙",vfr:"𝔳",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"𝕍",vopf:"𝕧",vprop:"∝",vrtri:"⊳",Vscr:"𝒱",vscr:"𝓋",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Ŵ",wcirc:"ŵ",wedbar:"⩟",Wedge:"⋀",wedge:"∧",wedgeq:"≙",weierp:"℘",Wfr:"𝔚",wfr:"𝔴",Wopf:"𝕎",wopf:"𝕨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"𝒲",wscr:"𝓌",xcap:"⋂",xcirc:"◯",xcup:"⋃",xdtri:"▽",Xfr:"𝔛",xfr:"𝔵",xhArr:"⟺",xharr:"⟷",Xi:"Ξ",xi:"ξ",xlArr:"⟸",xlarr:"⟵",xmap:"⟼",xnis:"⋻",xodot:"⨀",Xopf:"𝕏",xopf:"𝕩",xoplus:"⨁",xotime:"⨂",xrArr:"⟹",xrarr:"⟶",Xscr:"𝒳",xscr:"𝓍",xsqcup:"⨆",xuplus:"⨄",xutri:"△",xvee:"⋁",xwedge:"⋀",Yacute:"Ý",yacute:"ý",YAcy:"Я",yacy:"я",Ycirc:"Ŷ",ycirc:"ŷ",Ycy:"Ы",ycy:"ы",yen:"¥",Yfr:"𝔜",yfr:"𝔶",YIcy:"Ї",yicy:"ї",Yopf:"𝕐",yopf:"𝕪",Yscr:"𝒴",yscr:"𝓎",YUcy:"Ю",yucy:"ю",Yuml:"Ÿ",yuml:"ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Ż",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"​",Zeta:"Ζ",zeta:"ζ",Zfr:"ℨ",zfr:"𝔷",ZHcy:"Ж",zhcy:"ж",zigrarr:"⇝",Zopf:"ℤ",zopf:"𝕫",Zscr:"𝒵",zscr:"𝓏",zwj:"‍",zwnj:"‌"}),t.entityMap=t.HTML_ENTITIES}),To=(bo.XML_ENTITIES,Sa.NAMESPACE),sn=/[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/,tn=new RegExp("[\\-\\.0-9"+sn.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"),So=new RegExp("^"+sn.source+tn.source+"*(?::"+sn.source+tn.source+"*)?$"),wo=0,Eo=1,Co=2,ko=3,Io=4,xo=5,Ao=6,Do=7;function Po(e,t){this.message=e,this.locator=t,Error.captureStackTrace&&Error.captureStackTrace(this,Po)}function Lo(){}function Oo(e,t){return t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber,t}function Ro(e,t,i){for(var s=e.tagName,r=null,n=e.length;n--;){var a=e[n],o=a.qName,l=a.value,o=0<(h=o.indexOf(":"))?(d=a.prefix=o.slice(0,h),u=o.slice(h+1),"xmlns"===d&&u):(d=null,"xmlns"===(u=o)&&"");a.localName=u,!1!==o&&(null==r&&(r={},No(i,i={})),i[o]=r[o]=l,a.uri=To.XMLNS,t.startPrefixMapping(o,l))}for(var d,n=e.length;n--;)(d=(a=e[n]).prefix)&&("xml"===d&&(a.uri=To.XML),"xmlns"!==d)&&(a.uri=i[d||""]);var h,u=0<(h=s.indexOf(":"))?(d=e.prefix=s.slice(0,h),e.localName=s.slice(h+1)):(d=null,e.localName=s),c=e.uri=i[d||""];if(t.startElement(c,u,s,e),!e.closed)return e.currentNSMap=i,e.localNSMap=r,1;if(t.endElement(c,u,s),r)for(d in r)Object.prototype.hasOwnProperty.call(r,d)&&t.endPrefixMapping(d)}function No(e,t){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])}function Mo(){this.attributeNames={}}(Po.prototype=new Error).name=Po.name,Lo.prototype={parse:function(e,t,i){var s=this.domBuilder;s.startDocument(),No(t,t={}),function(i,e,s,r,n){function a(e){var t=e.slice(1,-1);return Object.hasOwnProperty.call(s,t)?s[t]:"#"===t.charAt(0)?65535<(t=parseInt(t.substr(1).replace("x","0x")))?(t-=65536,String.fromCharCode(55296+(t>>10),56320+(1023&t))):String.fromCharCode(t):(n.error("entity not found:"+e),e)}function t(e){var t;m",y+3),v=i.substring(y+2,_).replace(/[ \t\n\r]+$/g,""),b=c.pop(),T=(_<0?(v=i.substring(y+2).replace(/[\s<].*/,""),n.error("end tag name: "+v+" is not complete:"+b.tagName),_=y+1+v.length):v.match(/\s",t);if(s){e=e.substring(t,s).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);if(e)return e[0].length,i.processingInstruction(e[1],e[2]),s+2}return-1}(i,y,r);break;case"!":u&&o(y),_=function(e,t,i,s){{if("-"===e.charAt(t+2))return"-"===e.charAt(t+3)?(n=e.indexOf("--\x3e",t+4),t",t+9),i.startCDATA(),i.characters(e,t+9,n-t-9),i.endCDATA(),n+3;var r,s=function(e,t){var i,s=[],r=/'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;r.lastIndex=t,r.exec(e);for(;i=r.exec(e);)if(s.push(i),i[1])return s}(e,t),n=s.length;if(1":switch(d){case wo:s.setTagName(e.slice(t,l));case xo:case Ao:case Do:break;case Io:case Eo:"/"===(u=e.slice(t,l)).slice(-1)&&(s.closed=!0,u=u.slice(0,-1));case Co:d===Co&&(u=o),d==Io?(n.warning('attribute "'+u+'" missed quot(")!'),a(o,u,t)):(To.isHTML(i[""])&&u.match(/^(?:disabled|checked|selected)$/i)||n.warning('attribute "'+u+'" missed value!! "'+u+'" instead!!'),a(u,u,t));break;case ko:throw new Error("attribute value missed!!")}return l;case"€":h=" ";default:if(h<=" ")switch(d){case wo:s.setTagName(e.slice(t,l)),d=Ao;break;case Eo:o=e.slice(t,l),d=Co;break;case Io:var u=e.slice(t,l);n.warning('attribute "'+u+'" missed quot(")!!'),a(o,u,t);case xo:d=Ao}else switch(d){case Co:s.tagName,To.isHTML(i[""])&&o.match(/^(?:disabled|checked|selected)$/i)||n.warning('attribute "'+o+'" missed value!! "'+o+'" instead2!!'),a(o,o,t),t=l,d=Eo;break;case xo:n.warning('attribute space is required"'+o+'"!!');case Ao:d=Eo,t=l;break;case ko:d=Io,t=l;break;case Do:throw new Error("elements closed character '/' and '>' must be connected to")}}l++}}(i,y,E,C,a,n),k=E.length;if(!E.closed&&function(e,t,i,s){var r=s[i];null==r&&((r=e.lastIndexOf(""))",t),e=e.substring(t+1,n);if(/[&<]/.test(e))return/^script$/i.test(i)?r.characters(e,0,e.length):(e=e.replace(/&#?\w+;/g,s),r.characters(e,0,e.length)),n}return t+1}(i,_,E.tagName,a,r):_++}}catch(e){if(e instanceof Po)throw e;n.error("element parse error: "+e),_=-1}m<_?m=_:t(Math.max(y,m)+1)}}(e,t,i,s,this.errorHandler),s.endDocument()}},Mo.prototype={setTagName:function(e){if(!So.test(e))throw new Error("invalid tagName:"+e);this.tagName=e},addValue:function(e,t,i){if(!So.test(e))throw new Error("invalid attribute:"+e);this.attributeNames[e]=this.length,this[this.length++]={qName:e,value:t,offset:i}},length:0,getLocalName:function(e){return this[e].localName},getLocator:function(e){return this[e].locator},getQName:function(e){return this[e].qName},getURI:function(e){return this[e].uri},getValue:function(e){return this[e].value}};var en={XMLReader:Lo,ParseError:Po},Uo=Yr.DOMImplementation,Bo=Sa.NAMESPACE,Fo=en.ParseError,qo=en.XMLReader;function jo(e){return e.replace(/\r[\n\u0085]/g,"\n").replace(/[\r\u0085\u2028]/g,"\n")}function Vo(e){this.options=e||{locator:{}}}function Ho(){this.cdata=!1}function zo(e,t){t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber}function $o(e){if(e)return"\n@"+(e.systemId||"")+"#[line:"+e.lineNumber+",col:"+e.columnNumber+"]"}function Wo(e,t,i){return"string"==typeof e?e.substr(t,i):e.length>=t+i||t?new java.lang.String(e,t,i)+"":e}function Go(e,t){(e.currentElement||e.doc).appendChild(t)}Vo.prototype.parseFromString=function(e,t){var i=this.options,s=new qo,r=i.domBuilder||new Ho,n=i.errorHandler,a=i.locator,o=i.xmlns||{},t=/\/x?html?$/.test(t),l=t?bo.HTML_ENTITIES:bo.XML_ENTITIES,n=(a&&r.setDocumentLocator(a),s.errorHandler=function(s,e,r){if(!s){if(e instanceof Ho)return e;s=e}var n={},a=s instanceof Function;function t(t){var i=s[t];!i&&a&&(i=2==s.length?function(e){s(t,e)}:s),n[t]=i?function(e){i("[xmldom "+t+"]\t"+e+$o(r))}:function(){}}return r=r||{},t("warning"),t("error"),t("fatalError"),n}(n,r,a),s.domBuilder=i.domBuilder||r,t&&(o[""]=Bo.HTML),o.xml=o.xml||Bo.XML,i.normalizeLineEndings||jo);return e&&"string"==typeof e?s.parse(n(e),o,l):s.errorHandler.error("invalid doc source"),r.doc},Ho.prototype={startDocument:function(){this.doc=(new Uo).createDocument(null,null,null),this.locator&&(this.doc.documentURI=this.locator.systemId)},startElement:function(e,t,i,s){var r=this.doc,n=r.createElementNS(e,i||t),a=s.length;Go(this,n),this.currentElement=n,this.locator&&zo(this.locator,n);for(var o=0;o!!e&&"object"==typeof e,A=(...e)=>e.reduce((t,i)=>("object"==typeof i&&Object.keys(i).forEach(e=>{Array.isArray(t[e])&&Array.isArray(i[e])?t[e]=t[e].concat(i[e]):Ko(t[e])&&Ko(i[e])?t[e]=A(t[e],i[e]):t[e]=i[e]}),t),{}),Yo=t=>Object.keys(t).map(e=>t[e]),Qo=(t,i)=>{var s=[];for(let e=t;ee.reduce((e,t)=>e.concat(t),[]),Zo=t=>{if(!t.length)return[];var i=[];for(let e=0;ee.reduce((e,t,i)=>(t[s]&&e.push(i),e),[]),tl=(e,i)=>Yo(e.reduce((t,e)=>(e.forEach(e=>{t[i(e)]=e}),t),{}));var il={INVALID_NUMBER_OF_PERIOD:"INVALID_NUMBER_OF_PERIOD",INVALID_NUMBER_OF_CONTENT_STEERING:"INVALID_NUMBER_OF_CONTENT_STEERING",DASH_EMPTY_MANIFEST:"DASH_EMPTY_MANIFEST",DASH_INVALID_XML:"DASH_INVALID_XML",NO_BASE_URL:"NO_BASE_URL",MISSING_SEGMENT_INFORMATION:"MISSING_SEGMENT_INFORMATION",SEGMENT_TIME_UNSPECIFIED:"SEGMENT_TIME_UNSPECIFIED",UNSUPPORTED_UTC_TIMING_SCHEME:"UNSUPPORTED_UTC_TIMING_SCHEME"};let sl=({baseUrl:s="",source:r="",range:n="",indexRange:a=""})=>{s={uri:r,resolvedUri:Fn(s||"",r)};if(n||a){r=(n||a).split("-");let e=window.BigInt?window.BigInt(r[0]):parseInt(r[0],10),t=window.BigInt?window.BigInt(r[1]):parseInt(r[1],10);e{let t;return t="bigint"==typeof e.offset||"bigint"==typeof e.length?window.BigInt(e.offset)+window.BigInt(e.length)-window.BigInt(1):e.offset+e.length-1,e.offset+"-"+t},nl=e=>(e&&"number"!=typeof e&&(e=parseInt(e,10)),isNaN(e)?null:e),al={static(e){var{duration:t,timescale:i=1,sourceDuration:s,periodDuration:r}=e,e=nl(e.endNumber),t=t/i;return"number"==typeof e?{start:0,end:e}:"number"==typeof r?{start:0,end:r/t}:{start:0,end:s/t}},dynamic(e){var{NOW:t,clientOffset:i,availabilityStartTime:s,timescale:r=1,duration:n,periodStart:a=0,minimumUpdatePeriod:o=0,timeShiftBufferDepth:l=1/0}=e,e=nl(e.endNumber),t=(t+i)/1e3,i=s+a,s=Math.ceil((t+o-i)*r/n),a=Math.floor((t-i-l)*r/n),o=Math.floor((t-i)*r/n);return{start:Math.max(0,a),end:"number"==typeof e?e:Math.min(s,o)}}},ol=n=>e=>{var{duration:t,timescale:i=1,periodStart:s,startNumber:r=1}=n;return{number:r+e,duration:t/i,timeline:s,time:e*t}},ll=e=>{var{type:t,duration:i,timescale:s=1,periodDuration:r,sourceDuration:n}=e,{start:a,end:o}=al[t](e),a=Qo(a,o).map(ol(e));return"static"===t&&(a[o=a.length-1].duration=("number"==typeof r?r:n)-i/s*o),a},dl=e=>{var{baseUrl:t,initialization:i={},sourceDuration:s,indexRange:r="",periodStart:n,presentationTime:a,number:o=0,duration:l}=e;if(t)return i=sl({baseUrl:t,source:i.sourceURL,range:i.range}),(t=sl({baseUrl:t,source:t,indexRange:r})).map=i,l?(r=ll(e)).length&&(t.duration=r[0].duration,t.timeline=r[0].timeline):s&&(t.duration=s,t.timeline=n),t.presentationTime=a||n,t.number=o,[t];throw new Error(il.NO_BASE_URL)},hl=(e,i,s)=>{var r=e.sidx.map||null,n=e.sidx.duration,a=e.timeline||0,t=e.sidx.byterange,t=t.offset+t.length,o=i.timescale,l=i.references.filter(e=>1!==e.referenceType),d=[],h=e.endList?"static":"dynamic",u=e.sidx.timeline;let c=u,p=e.mediaSequence||0,m;m="bigint"==typeof i.firstOffset?window.BigInt(t)+i.firstOffset:t+i.firstOffset;for(let t=0;ttl(e,({timeline:e})=>e).sort((e,t)=>e.timeline>t.timeline?1:-1),ml=(t,i)=>{for(let e=0;e{let r=[];return _a(e,ul,(e,t,i,s)=>{r=r.concat(e.playlists||[])}),r},fl=({playlist:i,mediaSequence:e})=>{i.mediaSequence=e,i.segments.forEach((e,t)=>{e.number=i.mediaSequence+t})},yl=({oldPlaylists:t,newPlaylists:e,timelineStarts:r})=>{e.forEach(i=>{i.discontinuitySequence=r.findIndex(function({timeline:e}){return e===i.timeline});var e=ml(t,i.attributes.NAME);if(e&&!i.sidx){let t=i.segments[0];var s=e.segments.findIndex(function(e){return Math.abs(e.presentationTime-t.presentationTime)e.timeline||e.segments.length&&i.timeline>e.segments[e.segments.length-1].timeline)&&i.discontinuitySequence--):(e.segments[s].discontinuity&&!t.discontinuity&&(t.discontinuity=!0,i.discontinuityStarts.unshift(0),i.discontinuitySequence--),fl({playlist:i,mediaSequence:e.segments[s].number}))}})},_l=({oldManifest:e,newManifest:t})=>{var i=e.playlists.concat(gl(e)),s=t.playlists.concat(gl(t));return t.timelineStarts=pl([e.timelineStarts,t.timelineStarts]),yl({oldPlaylists:i,newPlaylists:s,timelineStarts:t.timelineStarts}),t},vl=e=>e&&e.uri+"-"+rl(e.byterange),bl=e=>{e=e.reduce(function(e,t){return e[t.attributes.baseUrl]||(e[t.attributes.baseUrl]=[]),e[t.attributes.baseUrl].push(t),e},{});let t=[];return Object.values(e).forEach(e=>{e=Yo(e.reduce((e,t)=>{var i=t.attributes.id+(t.attributes.lang||"");return e[i]?(t.segments&&(t.segments[0]&&(t.segments[0].discontinuity=!0),e[i].segments.push(...t.segments)),t.attributes.contentProtection&&(e[i].attributes.contentProtection=t.attributes.contentProtection)):(e[i]=t,e[i].attributes.timelineStarts=[]),e[i].attributes.timelineStarts.push({start:t.attributes.periodStart,timeline:t.attributes.periodStart}),e},{}));t=t.concat(e)}),t.map(e=>(e.discontinuityStarts=el(e.segments||[],"discontinuity"),e))},Tl=(e,t)=>{var i=vl(e.sidx),t=i&&t[i]&&t[i].sidx;return t&&hl(e,t,e.sidx.resolvedUri),e},Sl=(e,t={})=>{if(Object.keys(t).length)for(var i in e)e[i]=Tl(e[i],t);return e},wl=({attributes:e,segments:t,sidx:i,mediaSequence:s,discontinuitySequence:r,discontinuityStarts:n},a)=>{r={attributes:{NAME:e.id,BANDWIDTH:e.bandwidth,CODECS:e.codecs,"PROGRAM-ID":1},uri:"",endList:"static"===e.type,timeline:e.periodStart,resolvedUri:e.baseUrl||"",targetDuration:e.duration,discontinuitySequence:r,discontinuityStarts:n,timelineStarts:e.timelineStarts,mediaSequence:s,segments:t};return e.contentProtection&&(r.contentProtection=e.contentProtection),e.serviceLocation&&(r.attributes.serviceLocation=e.serviceLocation),i&&(r.sidx=i),a&&(r.attributes.AUDIO="audio",r.attributes.SUBTITLES="subs"),r},El=({attributes:e,segments:t,mediaSequence:i,discontinuityStarts:s,discontinuitySequence:r})=>{"undefined"==typeof t&&(t=[{uri:e.baseUrl,timeline:e.periodStart,resolvedUri:e.baseUrl||"",duration:e.sourceDuration,number:0}],e.duration=e.sourceDuration);var n={NAME:e.id,BANDWIDTH:e.bandwidth,"PROGRAM-ID":1},n=(e.codecs&&(n.CODECS=e.codecs),{attributes:n,uri:"",endList:"static"===e.type,timeline:e.periodStart,resolvedUri:e.baseUrl||"",targetDuration:e.duration,timelineStarts:e.timelineStarts,discontinuityStarts:s,discontinuitySequence:r,mediaSequence:i,segments:t});return e.serviceLocation&&(n.attributes.serviceLocation=e.serviceLocation),n},Cl=(e,n={},a=!1)=>{let o;e=e.reduce((e,t)=>{var i=t.attributes.role&&t.attributes.role.value||"",s=t.attributes.lang||"";let r=t.attributes.label||"main";e[r=s&&!t.attributes.label?t.attributes.lang+(i?` (${i})`:""):r]||(e[r]={language:s,autoselect:!0,default:"main"===i,playlists:[],uri:""});s=Tl(wl(t,a),n);return e[r].playlists.push(s),"undefined"==typeof o&&"main"===i&&((o=t).default=!0),e},{});return o||(e[Object.keys(e)[0]].default=!0),e},kl=(e,r={})=>e.reduce((e,t)=>{var i=t.attributes.label||t.attributes.lang||"text",s=t.attributes.lang||"und";return e[i]||(e[i]={language:s,default:!1,autoselect:!1,playlists:[],uri:""}),e[i].playlists.push(Tl(El(t),r)),e},{}),Il=e=>e.reduce((s,e)=>(e&&e.forEach(e=>{var{channel:t,language:i}=e;s[i]={autoselect:!1,default:!1,instreamId:t,language:i},e.hasOwnProperty("aspectRatio")&&(s[i].aspectRatio=e.aspectRatio),e.hasOwnProperty("easyReader")&&(s[i].easyReader=e.easyReader),e.hasOwnProperty("3D")&&(s[i]["3D"]=e["3D"])}),s),{}),xl=({attributes:e,segments:t,sidx:i,discontinuityStarts:s})=>{s={attributes:{NAME:e.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:e.width,height:e.height},CODECS:e.codecs,BANDWIDTH:e.bandwidth,"PROGRAM-ID":1},uri:"",endList:"static"===e.type,timeline:e.periodStart,resolvedUri:e.baseUrl||"",targetDuration:e.duration,discontinuityStarts:s,timelineStarts:e.timelineStarts,segments:t};return e.frameRate&&(s.attributes["FRAME-RATE"]=e.frameRate),e.contentProtection&&(s.contentProtection=e.contentProtection),e.serviceLocation&&(s.attributes.serviceLocation=e.serviceLocation),i&&(s.sidx=i),s},Al=({attributes:e})=>"video/mp4"===e.mimeType||"video/webm"===e.mimeType||"video"===e.contentType,Dl=({attributes:e})=>"audio/mp4"===e.mimeType||"audio/webm"===e.mimeType||"audio"===e.contentType,Pl=({attributes:e})=>"text/vtt"===e.mimeType||"text"===e.contentType,Ll=(e,i)=>{e.forEach(t=>{t.mediaSequence=0,t.discontinuitySequence=i.findIndex(function({timeline:e}){return e===t.timeline}),t.segments&&t.segments.forEach((e,t)=>{e.number=t})})},Ol=i=>i?Object.keys(i).reduce((e,t)=>{t=i[t];return e.concat(t.playlists)},[]):[],Rl=({dashPlaylists:e,locations:t,contentSteering:i,sidxMapping:s={},previousManifest:r,eventStream:n})=>{var a,o,l,d,h,u,c;return e.length?({sourceDuration:d,type:u,suggestedPresentationDelay:c,minimumUpdatePeriod:h}=e[0].attributes,a=bl(e.filter(Al)).map(xl),o=bl(e.filter(Dl)),l=bl(e.filter(Pl)),e=e.map(e=>e.attributes.captionServices).filter(Boolean),d={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:{AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},uri:"",duration:d,playlists:Sl(a,s)},0<=h&&(d.minimumUpdatePeriod=1e3*h),t&&(d.locations=t),i&&(d.contentSteering=i),"dynamic"===u&&(d.suggestedPresentationDelay=c),n&&0e),d.timelineStarts=pl(c),Ll(u,d.timelineStarts),t&&(d.mediaGroups.AUDIO.audio=t),i&&(d.mediaGroups.SUBTITLES.subs=i),e.length&&(d.mediaGroups["CLOSED-CAPTIONS"].cc=Il(e)),r?_l({oldManifest:r,newManifest:d}):d):{}},Nl=(e,t,i)=>{var{NOW:e,clientOffset:s,availabilityStartTime:r,timescale:n=1,periodStart:a=0,minimumUpdatePeriod:o=0}=e;return Math.ceil((((e+s)/1e3+o-(r+a))*n-t)/i)},Ml=(s,r)=>{var{type:n,minimumUpdatePeriod:a=0,media:o="",sourceDuration:l,timescale:d=1,startNumber:h=1,periodStart:u}=s,c=[];let p=-1;for(let i=0;ip&&(p=m);let e;e=f<0?(m=i+1)===r.length?"dynamic"===n&&0(e,t,i,s)=>{return"$$"===e?"$":"undefined"==typeof r[t]?e:(e=""+r[t],"RepresentationID"===t||(s=i?parseInt(s,10):1)<=e.length?e:new Array(s-e.length+1).join("0")+e)},Fl=(e,t)=>e.replace(Ul,Bl(t)),ql=(e,t)=>e.duration||t?e.duration?ll(e):Ml(e,t):[{number:e.startNumber||1,duration:e.sourceDuration,time:0,timeline:e.periodStart}],jl=(s,e)=>{let r={RepresentationID:s.id,Bandwidth:s.bandwidth||0};var{initialization:t={sourceURL:"",range:""}}=s;let n=sl({baseUrl:s.baseUrl,source:Fl(t.sourceURL,r),range:t.range});return ql(s,e).map(e=>{r.Number=e.number,r.Time=e.time;var t=Fl(s.media||"",r),i=s.timescale||1,i=s.periodStart+(e.time-(s.presentationTimeOffset||0))/i;return{uri:t,timeline:e.timeline,duration:e.duration,resolvedUri:Fn(s.baseUrl||"",t),map:n,number:e.number,presentationTime:i}})},Vl=(e,t)=>{var{baseUrl:e,initialization:i={}}=e,i=sl({baseUrl:e,source:i.sourceURL,range:i.range}),e=sl({baseUrl:e,source:t.media,range:t.mediaRange});return e.map=i,e},Hl=(r,e)=>{let{duration:t,segmentUrls:i=[],periodStart:n}=r;if(!t&&!e||t&&e)throw new Error(il.SEGMENT_TIME_UNSPECIFIED);let a=i.map(e=>Vl(r,e)),s;return t&&(s=ll(r)),(s=e?Ml(r,e):s).map((e,t)=>{var i,s;if(a[t])return t=a[t],i=r.timescale||1,s=r.presentationTimeOffset||0,t.timeline=e.timeline,t.duration=e.duration,t.number=e.number,t.presentationTime=n+(e.time-s)/i,t}).filter(e=>e)},zl=({attributes:e,segmentInfo:t})=>{let i,s;t.template?(s=jl,i=A(e,t.template)):t.base?(s=dl,i=A(e,t.base)):t.list&&(s=Hl,i=A(e,t.list));var r,n,a,e={attributes:e};return s&&(r=s(i,t.segmentTimeline),i.duration?({duration:n,timescale:a=1}=i,i.duration=n/a):r.length?i.duration=r.reduce((e,t)=>Math.max(e,Math.ceil(t.duration)),0):i.duration=0,e.attributes=i,e.segments=r,t.base)&&i.indexRange&&(e.sidx=r[0],e.segments=[]),e},$l=e=>e.map(zl),D=(e,t)=>Zo(e.childNodes).filter(({tagName:e})=>e===t),Wl=e=>e.textContent.trim(),Gl=e=>{var t,i,s,r,n,e=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(e);return e?([e,t,i,s,r,n]=e.slice(1),31536e3*parseFloat(e||0)+2592e3*parseFloat(t||0)+86400*parseFloat(i||0)+3600*parseFloat(s||0)+60*parseFloat(r||0)+parseFloat(n||0)):0},Xl={mediaPresentationDuration(e){return Gl(e)},availabilityStartTime(e){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(e=e)&&(e+="Z"),Date.parse(e)/1e3},minimumUpdatePeriod(e){return Gl(e)},suggestedPresentationDelay(e){return Gl(e)},type(e){return e},timeShiftBufferDepth(e){return Gl(e)},start(e){return Gl(e)},width(e){return parseInt(e,10)},height(e){return parseInt(e,10)},bandwidth(e){return parseInt(e,10)},frameRate(e){return parseFloat(e.split("/").reduce((e,t)=>e/t))},startNumber(e){return parseInt(e,10)},timescale(e){return parseInt(e,10)},presentationTimeOffset(e){return parseInt(e,10)},duration(e){var t=parseInt(e,10);return isNaN(t)?Gl(e):t},d(e){return parseInt(e,10)},t(e){return parseInt(e,10)},r(e){return parseInt(e,10)},presentationTime(e){return parseInt(e,10)},DEFAULT(e){return e}},P=e=>e&&e.attributes?Zo(e.attributes).reduce((e,t)=>{var i=Xl[t.name]||Xl.DEFAULT;return e[t.name]=i(t.value),e},{}):{},Kl={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime","urn:mpeg:dash:mp4protection:2011":"mp4protection"},Yl=(e,t)=>t.length?Jo(e.map(function(s){return t.map(function(e){var t=Wl(e),i=Fn(s.baseUrl,t),e=A(P(e),{baseUrl:i});return i!==t&&!e.serviceLocation&&s.serviceLocation&&(e.serviceLocation=s.serviceLocation),e})})):e,Ql=e=>{var t=D(e,"SegmentTemplate")[0],i=D(e,"SegmentList")[0],s=i&&D(i,"SegmentURL").map(e=>A({tag:"SegmentURL"},P(e))),e=D(e,"SegmentBase")[0],r=i||t,r=r&&D(r,"SegmentTimeline")[0],n=i||e||t,n=n&&D(n,"Initialization")[0],t=t&&P(t);t&&n?t.initialization=n&&P(n):t&&t.initialization&&(t.initialization={sourceURL:t.initialization});let a={template:t,segmentTimeline:r&&D(r,"S").map(e=>P(e)),list:i&&A(P(i),{segmentUrls:s,initialization:P(n)}),base:e&&A(P(e),{initialization:P(n)})};return Object.keys(a).forEach(e=>{a[e]||delete a[e]}),a},Jl=(r,n,a)=>e=>{var t=D(e,"BaseURL"),t=Yl(n,t);let i=A(r,P(e)),s=Ql(e);return t.map(e=>({segmentInfo:A(a,s),attributes:A(i,e)}))},Zl=e=>e.reduce((e,t)=>{var i=P(t),s=(i.schemeIdUri&&(i.schemeIdUri=i.schemeIdUri.toLowerCase()),Kl[i.schemeIdUri]);return s&&(e[s]={attributes:i},i=D(t,"cenc:pssh")[0])&&(t=Wl(i),e[s].pssh=t&&qn(t)),e},{}),ed=e=>{return"urn:scte:dash:cc:cea-608:2015"===e.schemeIdUri?("string"!=typeof e.value?[]:e.value.split(";")).map(e=>{let t,i;return i=e,/^CC\d=/.test(e)?[t,i]=e.split("="):/^CC\d$/.test(e)&&(t=e),{channel:t,language:i}}):"urn:scte:dash:cc:cea-708:2015"===e.schemeIdUri?("string"!=typeof e.value?[]:e.value.split(";")).map(e=>{let i={channel:void 0,language:void 0,aspectRatio:1,easyReader:0,"3D":0};var t,s;return/=/.test(e)?([t,s=""]=e.split("="),i.channel=t,i.language=e,s.split(",").forEach(e=>{var[e,t]=e.split(":");"lang"===e?i.language=t:"er"===e?i.easyReader=Number(t):"war"===e?i.aspectRatio=Number(t):"3D"===e&&(i["3D"]=Number(t))})):i.language=e,i.channel&&(i.channel="SERVICE"+i.channel),i}):void 0},td=o=>Jo(D(o.node,"EventStream").map(e=>{let n=P(e),a=n.schemeIdUri;return D(e,"Event").map(e=>{var t=P(e),i=t.presentationTime||0,s=n.timescale||1,r=t.duration||0,i=i/s+o.attributes.start;return{schemeIdUri:a,value:n.value,id:t.id,start:i,end:i+r/s,messageData:Wl(e)||t.messageData,contentEncoding:n.contentEncoding,presentationTimeOffset:n.presentationTimeOffset||0}})})),id=(n,a,o)=>e=>{var t=P(e),i=Yl(a,D(e,"BaseURL")),s=D(e,"Role")[0],s={role:P(s)};let r=A(n,t,s);t=D(e,"Accessibility")[0],s=ed(P(t)),s&&(r=A(r,{captionServices:s})),t=D(e,"Label")[0],t&&t.childNodes.length&&(s=t.childNodes[0].nodeValue.trim(),r=A(r,{label:s})),t=Zl(D(e,"ContentProtection")),Object.keys(t).length&&(r=A(r,{contentProtection:t})),s=Ql(e),t=D(e,"Representation"),e=A(o,s);return Jo(t.map(Jl(r,i,e)))},sd=(n,a)=>(e,t)=>{var i=Yl(a,D(e.node,"BaseURL")),s=A(n,{periodStart:e.attributes.start}),r=("number"==typeof e.attributes.duration&&(s.periodDuration=e.attributes.duration),D(e.node,"AdaptationSet")),e=Ql(e.node);return Jo(r.map(id(s,i,e)))},rd=(e,t)=>{return 1"number"==typeof e.start?e.start:t&&"number"==typeof t.start&&"number"==typeof t.duration?t.start+t.duration:t||"static"!==i?null:0,ad=(e,t={})=>{var{manifestUri:t="",NOW:i=Date.now(),clientOffset:s=0,eventHandler:r=function(){}}=t,n=D(e,"Period");if(!n.length)throw new Error(il.INVALID_NUMBER_OF_PERIOD);var a=D(e,"Location");let o=P(e);t=Yl([{baseUrl:t}],D(e,"BaseURL")),e=D(e,"ContentSteering");o.type=o.type||"static",o.sourceDuration=o.mediaPresentationDuration||0,o.NOW=i,o.clientOffset=s,a.length&&(o.locations=a.map(Wl));let l=[];return n.forEach((e,t)=>{var i=P(e),t=l[t-1];i.start=nd({attributes:i,priorPeriodAttributes:t?t.attributes:null,mpdType:o.type}),l.push({node:e,attributes:i})}),{locations:o.locations,contentSteeringInfo:rd(e,r),representationInfo:Jo(l.map(sd(o,t))),eventStream:Jo(l.map(td))}},od=e=>{if(""===e)throw new Error(il.DASH_EMPTY_MANIFEST);var t,i=new Xo;let s;try{t=i.parseFromString(e,"application/xml"),s=t&&"MPD"===t.documentElement.tagName?t.documentElement:null}catch(e){}if(!s||s&&0(e=>{e=D(e,"UTCTiming")[0];if(!e)return null;var t=P(e);switch(t.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":t.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":t.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":t.method="DIRECT",t.value=Date.parse(t.value);break;default:throw new Error(il.UNSUPPORTED_UTC_TIMING_SCHEME)}return t})(od(e));function dd(e,t){var i,s,r;return void 0===t&&(t=0),(e=S(e)).length-t<10||!C(e,fd,{offset:t})?t:(t+=(void 0===(s=t)&&(s=0),r=(i=S(i=e))[s+5],i=i[s+6]<<21|i[s+7]<<14|i[s+8]<<7|i[s+9],(16&r)>>4?20+i:10+i),dd(e,t))}function hd(e,t,i){var s;return i>=t.length?t.length:(s=wd(t,i,!1),C(e.bytes,s.bytes)?i:hd(e,t,i+(e=wd(t,i+s.length)).length+e.value+s.length))}function ud(e,t){i=t,t=Array.isArray(i)?i.map(function(e){return Ed(e)}):[Ed(i)],e=S(e);var i,s=[];if(t.length)for(var r=0;re.length?e.length:o+a.value),o=e.subarray(o,l);C(t[0],n.bytes)&&(1===t.length?s.push(o):s=s.concat(ud(o,t.slice(1)))),r+=n.length+a.length+o.length}return s}function cd(e,t,i,s){void 0===s&&(s=1/0),e=S(e),i=[].concat(i);for(var r,n=0,a=0;n>1&63),-1!==i.indexOf(l)&&(r=n+o),n+=o+("h264"===t?1:2)}else n++}return e.subarray(0,0)}var pd=Math.pow(2,32),md=function(e){var t,e=new DataView(e.buffer,e.byteOffset,e.byteLength);return e.getBigUint64?(t=e.getBigUint64(0))>>7,referencedSize:2147483647&t.getUint32(s),subsegmentDuration:t.getUint32(s+4),startsWithSap:!!(128&e[s+8]),sapType:(112&e[s+8])>>>4,sapDeltaTime:268435455&t.getUint32(s+8)});return i},fd=S([73,68,51]),yd=function(e){return"string"==typeof e?ya(e):e},_d=function(e){return Array.isArray(e)?e.map(function(e){return yd(e)}):[yd(e)]},vd=function e(t,i,s){void 0===s&&(s=!1),i=_d(i),t=S(t);var r=[];if(i.length)for(var n=0;n>>0,o=t.subarray(n+4,n+8);if(0==a)break;a=n+a;if(a>t.length){if(s)break;a=t.length}var l=t.subarray(n+8,a);C(o,i[0])&&(1===i.length?r.push(l):r.push.apply(r,e(l,i.slice(1),s))),n=a}return r},bd={EBML:S([26,69,223,163]),DocType:S([66,130]),Segment:S([24,83,128,103]),SegmentInfo:S([21,73,169,102]),Tracks:S([22,84,174,107]),Track:S([174]),TrackNumber:S([215]),DefaultDuration:S([35,227,131]),TrackEntry:S([174]),TrackType:S([131]),FlagDefault:S([136]),CodecID:S([134]),CodecPrivate:S([99,162]),VideoTrack:S([224]),AudioTrack:S([225]),Cluster:S([31,67,182,117]),Timestamp:S([231]),TimestampScale:S([42,215,177]),BlockGroup:S([160]),BlockDuration:S([155]),Block:S([161]),SimpleBlock:S([163])},Td=[128,64,32,16,8,4,2,1],Sd=function(e){for(var t=1,i=0;it&&t.responseURL&&e!==t.responseURL?t.responseURL:e,Bd=e=>E.log.debug?E.log.debug.bind(E,"VHS:",e+" >"):function(){};function L(...e){var t=E.obj||E;return(t.merge||t.mergeOptions).apply(t,e)}function O(...e){var t=E.time||E;return(t.createTimeRanges||t.createTimeRanges).apply(t,e)}function Fd(e,i){return Gd(e,function(e,t){return e-Wd<=i&&t+Wd>=i})}function qd(e,t){return Gd(e,function(e){return e-$d>=t})}function jd(e){if(e&&e.length&&e.end)return e.end(e.length-1)}function Vd(t,i){let s=0;if(t&&t.length)for(let e=0;e{var i=[];if(!t||!t.length)return"";for(let e=0;e "+t.end(e));return i.join(", ")},Kd=t=>{var i=[];for(let e=0;e{if(!e.preload)return e.duration;let i=0;return(e.parts||[]).forEach(function(e){i+=e.duration}),(e.preloadHints||[]).forEach(function(e){"PART"===e.type&&(i+=t.partTargetDuration)}),i},Qd=e=>(e.segments||[]).reduce((i,s,r)=>(s.parts?s.parts.forEach(function(e,t){i.push({duration:e.duration,segmentIndex:r,partIndex:t,part:e,segment:s})}):i.push({duration:s.duration,segmentIndex:r,partIndex:null,segment:s,part:null}),i),[]),Jd=e=>{e=e.segments&&e.segments.length&&e.segments[e.segments.length-1];return e&&e.parts||[]},Zd=({preloadSegment:e})=>{var t;if(e)return{parts:e,preloadHints:t}=e,(t||[]).reduce((e,t)=>e+("PART"===t.type?1:0),0)+(e&&e.length?e.length:0)},eh=(e,t)=>{return t.endList?0:e&&e.suggestedPresentationDelay?e.suggestedPresentationDelay:(e=0Date.now()}function ah(e){return e.excludeUntil&&e.excludeUntil===1/0}function oh(e){var t=nh(e);return!e.disabled&&!t}function lh(e,t){return t.attributes&&t.attributes[e]}function dh(e,t){var i,s=e&&e.mediaGroups&&e.mediaGroups.AUDIO||{};let r=!1;for(i in s){for(var n in s[i])if(r=t(s[i][n]))break;if(r)break}return!!r}let hh=(e,t)=>{if(1===e.playlists.length)return!0;let i=t.attributes.BANDWIDTH||Number.MAX_VALUE;return 0===e.playlists.filter(e=>!!oh(e)&&(e.attributes.BANDWIDTH||0)!(!e&&!t||!e&&t||e&&!t||e!==t&&(!e.id||!t.id||e.id!==t.id)&&(!e.resolvedUri||!t.resolvedUri||e.resolvedUri!==t.resolvedUri)&&(!e.uri||!t.uri||e.uri!==t.uri)),ch=i=>{if(!i||!i.playlists||!i.playlists.length)return dh(i,e=>e.playlists&&e.playlists.length||e.uri);for(let e=0;eYn(e))){s=dh(i,e=>uh(t,e));if(!s)return!1}}return!0};var ph={liveEdgeDelay:eh,duration:rh,seekable:function(e,t,i){var s=t||0;let r=zd(e,t,!0,i);return null===r?O():O(s,r=r$d),m=0===o,p=p&&0<=o+$d;if(!m&&!p||e===l.length-1){if(a){if(0e+"-"+t,fh=(e,t,i)=>`placeholder-uri-${e}-${t}-`+i,yh=(r,n)=>{r.mediaGroups&&["AUDIO","SUBTITLES"].forEach(e=>{if(r.mediaGroups[e])for(var t in r.mediaGroups[e])for(var i in r.mediaGroups[e][t]){var s=r.mediaGroups[e][t][i];n(s,e,t,i)}})},_h=({playlist:e,uri:t,id:i})=>{e.id=i,e.playlistErrors_=0,t&&(e.uri=t),e.attributes=e.attributes||{}},vh=(o,e,l=fh)=>{o.uri=e;for(let e=0;e{if(!e.playlists||!e.playlists.length){if(i&&"AUDIO"===r&&!e.uri)for(let e=0;e{let t=e.playlists.length;for(;t--;){var i=e.playlists[t];_h({playlist:i,id:gh(t,i.uri)}),i.resolvedUri=Md(e.uri,i.uri),e.playlists[i.id]=i,(e.playlists[i.uri]=i).attributes.BANDWIDTH||mh.warn("Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.")}})(o),s=o,yh(s,e=>{e.uri&&(e.resolvedUri=Md(s.uri,e.uri))})};class bh{constructor(){this.offset_=null,this.pendingDateRanges_=new Map,this.processedDateRanges_=new Map}setOffset(e=[]){null===this.offset_&&e.length&&([e]=e,void 0!==e.programDateTime)&&(this.offset_=e.programDateTime/1e3)}setPendingDateRanges(e=[]){var t;e.length&&([t]=e,t=t.startDate.getTime(),this.trimProcessedDateRanges_(t),this.pendingDateRanges_=e.reduce((e,t)=>(e.set(t.id,t),e),new Map))}processDateRange(e){this.pendingDateRanges_.delete(e.id),this.processedDateRanges_.set(e.id,e)}getDateRangesToProcess(){if(null===this.offset_)return[];let i={},s=[];this.pendingDateRanges_.forEach((e,t)=>{this.processedDateRanges_.has(t)||(e.startTime=e.startDate.getTime()/1e3-this.offset_,e.processDateRange=()=>this.processDateRange(e),s.push(e),e.class&&(i[e.class]?(t=i[e.class].push(e),e.classListIndex=t-1):(i[e.class]=[e],e.classListIndex=0)))});for(var e of s){var t=i[e.class]||[];e.endDate?e.endTime=e.endDate.getTime()/1e3-this.offset_:e.endOnNext&&t[e.classListIndex+1]?e.endTime=t[e.classListIndex+1].startTime:e.duration?e.endTime=e.startTime+e.duration:e.plannedDuration?e.endTime=e.startTime+e.plannedDuration:e.endTime=e.startTime}return s}trimProcessedDateRanges_(i){new Map(this.processedDateRanges_).forEach((e,t)=>{e.startDate.getTime(){if(!kh(e,t))return!0;var i,t=t.attributes||{},s=e.mediaGroups.AUDIO[t.AUDIO];for(i in s)if(!s[i].uri&&!s[i].playlists)return!0;return!1})(e,t)||(t=Ih(function(e,t){if(e.mediaGroups.AUDIO&&t){var i=e.mediaGroups.AUDIO[t];if(i)for(var s in i){s=i[s];if(s.default&&s.playlists)return aa(s.playlists[0].attributes.CODECS)}}return null}(e,i.AUDIO)||[])).audio&&(s.audio=t.audio),s}let Eh=({requestType:e,request:t,error:i,parseFailure:s})=>{var r=t.status<200||299{t=t.attributes||{};return e&&e.mediaGroups&&e.mediaGroups.AUDIO&&t.AUDIO&&e.mediaGroups.AUDIO[t.AUDIO]},Ih=function(e){let s={};return e.forEach(({mediaType:e,type:t,details:i})=>{s[e]=s[e]||[],s[e].push(na(""+t+i))}),Object.keys(s).forEach(function(e){1{if(!t)return i;var s=L(t,i);if(t.preloadHints&&!i.preloadHints&&delete s.preloadHints,t.parts&&!i.parts)delete s.parts;else if(t.parts&&i.parts)for(let e=0;e{!e.resolvedUri&&e.uri&&(e.resolvedUri=Md(t,e.uri)),e.key&&!e.key.resolvedUri&&(e.key.resolvedUri=Md(t,e.key.uri)),e.map&&!e.map.resolvedUri&&(e.map.resolvedUri=Md(t,e.map.uri)),e.map&&e.map.key&&!e.map.key.resolvedUri&&(e.map.key.resolvedUri=Md(t,e.map.key.uri)),e.parts&&e.parts.length&&e.parts.forEach(e=>{e.resolvedUri||(e.resolvedUri=Md(t,e.uri))}),e.preloadHints&&e.preloadHints.length&&e.preloadHints.forEach(e=>{e.resolvedUri||(e.resolvedUri=Md(t,e.uri))})},Ph=(e,t)=>e===t||e.segments&&t.segments&&e.segments.length===t.segments.length&&e.endList===t.endList&&e.mediaSequence===t.mediaSequence&&e.preloadSegment===t.preloadSegment,Lh=(e,r,t=Ph)=>{var i=L(e,{}),s=i.playlists[r.id];if(!s)return null;if(t(s,r))return null;r.segments=xh(r);let n=L(s,r);if(n.preloadSegment&&!r.preloadSegment&&delete n.preloadSegment,s.segments){if(r.skip){r.segments=r.segments||[];for(let e=0;e{var s=e.slice(),r=t.slice(),n=(i=i||0,[]);let a;for(let e=0;e{Dh(e,n.resolvedUri)});for(let e=0;e{if(t.playlists)for(let e=0;e{var i=e.segments||[],i=i[i.length-1],s=i&&i.parts&&i.parts[i.parts.length-1],s=s&&s.duration||i&&i.duration;return t&&s?1e3*s:500*(e.partTargetDuration||e.targetDuration||10)},Rh=(e,t,i)=>{if(e){let r=[];return e.forEach(e=>{var t,i,s;e.attributes&&({BANDWIDTH:t,RESOLUTION:i,CODECS:s}=e.attributes,r.push({id:e.id,bandwidth:t,resolution:i,codecs:s}))}),{type:t,isLive:i,renditions:r}}};class Nh extends Zr{constructor(e,t,i={}){if(super(),!e)throw new Error("A non-empty playlist URL or object is required");this.logger_=Bd("PlaylistLoader");var{withCredentials:s=!1}=i,e=(this.src=e,this.vhs_=t,this.withCredentials=s,this.addDateRangesToTextTrack_=i.addDateRangesToTextTrack,t.options_);this.customTagParsers=e&&e.customTagParsers||[],this.customTagMappers=e&&e.customTagMappers||[],this.llhls=e&&e.llhls,this.dateRangesStorage_=new bh,this.state="HAVE_NOTHING",this.handleMediaupdatetimeout_=this.handleMediaupdatetimeout_.bind(this),this.on("mediaupdatetimeout",this.handleMediaupdatetimeout_),this.on("loadedplaylist",this.handleLoadedPlaylist_.bind(this))}handleLoadedPlaylist_(){var e=this.media();e&&(this.dateRangesStorage_.setOffset(e.segments),this.dateRangesStorage_.setPendingDateRanges(e.dateRanges),(e=this.dateRangesStorage_.getDateRangesToProcess()).length)&&this.addDateRangesToTextTrack_&&this.addDateRangesToTextTrack_(e)}handleMediaupdatetimeout_(){if("HAVE_METADATA"===this.state){var t=this.media();let e=Md(this.main.uri,t.uri);this.llhls&&(e=((e,t)=>{if(!t.endList&&t.serverControl){let i={};if(t.serverControl.canBlockReload){var s,r=t.preloadSegment;let e=t.mediaSequence+t.segments.length;r&&(r=r.parts||[],-1<(s=Zd(t)-1)&&s!=r.length-1&&(i._HLS_part=s),-1{if(this.request)return e?this.playlistRequestError(this.request,this.media(),"HAVE_METADATA"):void this.haveMetadata({playlistString:this.request.responseText,url:this.media().uri,id:this.media().id})})}}playlistRequestError(e,t,i){var{uri:t,id:s}=t;this.request=null,i&&(this.state=i),this.error={playlist:this.main.playlists[s],status:e.status,message:`HLS playlist request error at URL: ${t}.`,responseText:e.responseText,code:500<=e.status?4:2,metadata:Eh({requestType:e.requestType,request:e,error:e.error})},this.trigger("error")}parseManifest_({url:t,manifestString:e}){try{var i=(({onwarn:t,oninfo:e,manifestString:i,customTagParsers:s=[],customTagMappers:r=[],llhls:n})=>{let a=new Kn,o=(t&&a.on("warn",t),e&&a.on("info",e),s.forEach(e=>a.addParser(e)),r.forEach(e=>a.addTagMapper(e)),a.push(i),a.end(),a.manifest);if(n||(["preloadSegment","skip","serverControl","renditionReports","partInf","partTargetDuration"].forEach(function(e){o.hasOwnProperty(e)&&delete o[e]}),o.segments&&o.segments.forEach(function(t){["parts","preloadHints"].forEach(function(e){t.hasOwnProperty(e)&&delete t[e]})})),!o.targetDuration){let e=10;o.segments&&o.segments.length&&(e=o.segments.reduce((e,t)=>Math.max(e,t.duration),0)),t&&t({message:"manifest has no targetDuration defaulting to "+e}),o.targetDuration=e}e=Jd(o);return e.length&&!o.partTargetDuration&&(s=e.reduce((e,t)=>Math.max(e,t.duration),0),t&&(t({message:"manifest has no partTargetDuration defaulting to "+s}),mh.error("LL-HLS manifest has parts but lacks required #EXT-X-PART-INF:PART-TARGET value. See https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-09#section-4.4.3.7. Playback is not guaranteed.")),o.partTargetDuration=s),o})({onwarn:({message:e})=>this.logger_(`m3u8-parser warn for ${t}: `+e),oninfo:({message:e})=>this.logger_(`m3u8-parser info for ${t}: `+e),manifestString:e,customTagParsers:this.customTagParsers,customTagMappers:this.customTagMappers,llhls:this.llhls});return i.playlists&&i.playlists.length&&this.excludeAudioOnlyVariants(i.playlists),i}catch(e){this.error=e,this.error.metadata={errorType:E.Error.StreamingHlsPlaylistParserError,error:e}}}excludeAudioOnlyVariants(e){let t=e=>{var{width:t,height:i}=(e.attributes||{}).RESOLUTION||{};return!(!t||!i)||(t=Th(e)||[],i=Ih(t),Boolean(i.video))};e.some(t)&&e.forEach(e=>{t(e)||(e.excludeUntil=1/0)})}haveMetadata({playlistString:e,playlistObject:t,url:i,id:s}){this.request=null,this.state="HAVE_METADATA";var r={playlistInfo:{type:"media",uri:i}},t=(this.trigger({type:"playlistparsestart",metadata:r}),t||this.parseManifest_({url:i,manifestString:e})),e=(t.lastRequest=Date.now(),_h({playlist:t,uri:i,id:s}),Lh(this.main,t));this.targetDuration=t.partTargetDuration||t.targetDuration,this.pendingMedia_=null,e?(this.main=e,this.media_=this.main.playlists[s]):this.trigger("playlistunchanged"),this.updateMediaUpdateTimeout_(Oh(this.media(),!!e)),r.parsedPlaylist=Rh(this.main.playlists,r.playlistInfo.type,!this.media_.endList),this.trigger({type:"playlistparsecomplete",metadata:r}),this.trigger("loadedplaylist")}dispose(){this.trigger("dispose"),this.stopRequest(),window.clearTimeout(this.mediaUpdateTimeout),window.clearTimeout(this.finalRenditionTimeout),this.dateRangesStorage_=new bh,this.off()}stopRequest(){var e;this.request&&(e=this.request,this.request=null,e.onreadystatechange=null,e.abort())}media(r,e){if(!r)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);if("string"==typeof r){if(!this.main.playlists[r])throw new Error("Unknown playlist URI: "+r);r=this.main.playlists[r]}if(window.clearTimeout(this.finalRenditionTimeout),e)e=(r.partTargetDuration||r.targetDuration)/2*1e3||5e3,this.finalRenditionTimeout=window.setTimeout(this.media.bind(this,r,!1),e);else{let s=this.state;var e=!this.media_||r.id!==this.media_.id,t=this.main.playlists[r.id];if(t&&t.endList||r.endList&&r.segments.length)this.request&&(this.request.onreadystatechange=null,this.request.abort(),this.request=null),this.state="HAVE_METADATA",this.media_=r,e&&(this.trigger("mediachanging"),"HAVE_MAIN_MANIFEST"===s?this.trigger("loadedmetadata"):this.trigger("mediachange"));else if(this.updateMediaUpdateTimeout_(Oh(r,!0)),e){if(this.state="SWITCHING_MEDIA",this.request){if(r.resolvedUri===this.request.url)return;this.request.onreadystatechange=null,this.request.abort(),this.request=null}this.media_&&this.trigger("mediachanging");let i={playlistInfo:{type:"media",uri:(this.pendingMedia_=r).uri}};this.trigger({type:"playlistrequeststart",metadata:i}),this.request=this.vhs_.xhr({uri:r.resolvedUri,withCredentials:this.withCredentials,requestType:"hls-playlist"},(e,t)=>{if(this.request){if(r.lastRequest=Date.now(),r.resolvedUri=Ud(r.resolvedUri,t),e)return this.playlistRequestError(this.request,r,s);this.trigger({type:"playlistrequestcomplete",metadata:i}),this.haveMetadata({playlistString:t.responseText,url:r.uri,id:r.id}),"HAVE_MAIN_MANIFEST"===s?this.trigger("loadedmetadata"):this.trigger("mediachange")}})}}}pause(){this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null),this.stopRequest(),"HAVE_NOTHING"===this.state&&(this.started=!1),"SWITCHING_MEDIA"===this.state?this.media_?this.state="HAVE_METADATA":this.state="HAVE_MAIN_MANIFEST":"HAVE_CURRENT_METADATA"===this.state&&(this.state="HAVE_METADATA")}load(e){this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null);var t=this.media();e?(e=t?(t.partTargetDuration||t.targetDuration)/2*1e3:5e3,this.mediaUpdateTimeout=window.setTimeout(()=>{this.mediaUpdateTimeout=null,this.load()},e)):this.started?t&&!t.endList?this.trigger("mediaupdatetimeout"):this.trigger("loadedplaylist"):this.start()}updateMediaUpdateTimeout_(e){this.mediaUpdateTimeout&&(window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null),this.media()&&!this.media().endList&&(this.mediaUpdateTimeout=window.setTimeout(()=>{this.mediaUpdateTimeout=null,this.trigger("mediaupdatetimeout"),this.updateMediaUpdateTimeout_(e)},e))}start(){if(this.started=!0,"object"==typeof this.src)this.src.uri||(this.src.uri=window.location.href),this.src.resolvedUri=this.src.uri,setTimeout(()=>{this.setupInitialPlaylist(this.src)},0);else{let i={playlistInfo:{type:"multivariant",uri:this.src}};this.trigger({type:"playlistrequeststart",metadata:i}),this.request=this.vhs_.xhr({uri:this.src,withCredentials:this.withCredentials,requestType:"hls-playlist"},(e,t)=>{if(this.request){if(this.request=null,e)return this.error={status:t.status,message:`HLS playlist request error at URL: ${this.src}.`,responseText:t.responseText,code:2,metadata:Eh({requestType:t.requestType,request:t,error:e})},"HAVE_NOTHING"===this.state&&(this.started=!1),this.trigger("error");this.trigger({type:"playlistrequestcomplete",metadata:i}),this.src=Ud(this.src,t),this.trigger({type:"playlistparsestart",metadata:i});e=this.parseManifest_({manifestString:t.responseText,url:this.src});i.parsedPlaylist=Rh(e.playlists,i.playlistInfo.type,!1),this.trigger({type:"playlistparsecomplete",metadata:i}),this.setupInitialPlaylist(e)}})}}srcUri(){return"string"==typeof this.src?this.src:this.src.uri}setupInitialPlaylist(e){var t,i,s,r;this.state="HAVE_MAIN_MANIFEST",e.playlists?(this.main=e,vh(this.main,this.srcUri()),e.playlists.forEach(t=>{t.segments=xh(t),t.segments.forEach(e=>{Dh(e,t.resolvedUri)})}),this.trigger("loadedplaylist"),this.request||this.media(this.main.playlists[0])):(t=this.srcUri()||window.location.href,this.main=(i=t,s=gh(0,i),(r={mediaGroups:{AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},uri:window.location.href,resolvedUri:window.location.href,playlists:[{uri:i,id:s,resolvedUri:i,attributes:{}}]}).playlists[s]=r.playlists[0],r.playlists[i]=r.playlists[0],r),this.haveMetadata({playlistObject:e,url:t,id:this.main.playlists[0].id}),this.trigger("loadedmetadata"))}updateOrDeleteClone(e,t){var i=this.main,s=e.ID;let r=i.playlists.length;for(;r--;){var n,a,o,l,d,h=i.playlists[r];h.attributes["PATHWAY-ID"]===s&&(n=h.resolvedUri,a=h.id,t?(o=this.createCloneURI_(h.resolvedUri,e),l=gh(s,o),d=this.createCloneAttributes_(s,h.attributes),h=this.createClonePlaylist_(h,l,e,d),i.playlists[r]=h,i.playlists[l]=h,i.playlists[o]=h):i.playlists.splice(r,1),delete i.playlists[a],delete i.playlists[n])}this.updateOrDeleteCloneMedia(e,t)}updateOrDeleteCloneMedia(e,t){let s=this.main,r=e.ID;["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(e=>{if(s.mediaGroups[e]&&s.mediaGroups[e][r])for(var t in s.mediaGroups[e])if(t===r){for(var i in s.mediaGroups[e][t])s.mediaGroups[e][t][i].playlists.forEach((e,t)=>{var e=s.playlists[e.id],i=e.id,e=e.resolvedUri;delete s.playlists[i],delete s.playlists[e]});delete s.mediaGroups[e][t]}}),t&&this.createClonedMediaGroups_(e)}addClonePathway(e,t={}){var i=this.main,s=i.playlists.length,r=this.createCloneURI_(t.resolvedUri,e),n=gh(e.ID,r),a=this.createCloneAttributes_(e.ID,t.attributes),t=this.createClonePlaylist_(t,n,e,a);i.playlists[s]=t,i.playlists[n]=t,i.playlists[r]=t,this.createClonedMediaGroups_(e)}createClonedMediaGroups_(l){let d=l.ID,s=l["BASE-ID"],h=this.main;["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(o=>{if(h.mediaGroups[o]&&!h.mediaGroups[o][d])for(var e in h.mediaGroups[o])if(e===s){h.mediaGroups[o][d]={};for(let a in h.mediaGroups[o][e]){var t=h.mediaGroups[o][e][a];h.mediaGroups[o][d][a]=f({},t);let n=h.mediaGroups[o][d][a];var i=this.createCloneURI_(t.resolvedUri,l);n.resolvedUri=i,n.uri=i,n.playlists=[],t.playlists.forEach((e,t)=>{var i,s=h.playlists[e.id],r=fh(o,d,a),r=gh(d,r);s&&!h.playlists[r]&&(i=(s=this.createClonePlaylist_(s,r,l)).resolvedUri,h.playlists[r]=s,h.playlists[i]=s),n.playlists[t]=this.createClonePlaylist_(e,r,l)})}}})}createClonePlaylist_(e,t,i,s){i=this.createCloneURI_(e.resolvedUri,i),i={resolvedUri:i,uri:i,id:t};return e.segments&&(i.segments=[]),s&&(i.attributes=s),L(e,i)}createCloneURI_(e,t){var i,s=new URL(e),r=(s.hostname=t["URI-REPLACEMENT"].HOST,t["URI-REPLACEMENT"].PARAMS);for(i of Object.keys(r))s.searchParams.set(i,r[i]);return s.href}createCloneAttributes_(t,i){let s={"PATHWAY-ID":t};return["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(e=>{i[e]&&(s[e]=t)}),s}getKeyIdSet(e){var t=new Set;if(e&&e.contentProtection)for(var i in e.contentProtection)e.contentProtection[i]&&e.contentProtection[i].attributes&&e.contentProtection[i].attributes.keyId&&(i=e.contentProtection[i].attributes.keyId,t.add(i.toLowerCase()));return t}}function Mh(e,t,i,s){var r="arraybuffer"===e.responseType?e.response:e.responseText;!t&&r&&(e.responseTime=Date.now(),e.roundTripTime=e.responseTime-e.requestTime,e.bytesReceived=r.byteLength||r.length,e.bandwidth||(e.bandwidth=Math.floor(e.bytesReceived/e.roundTripTime*8*1e3))),i.headers&&(e.responseHeaders=i.headers),t&&"ETIMEDOUT"===t.code&&(e.timedout=!0),s(t=t||e.aborted||200===i.statusCode||206===i.statusCode||0===i.statusCode?t:new Error("XHR Failed with a response of: "+(e&&(r||e.responseText))),e)}function Uh(){function d(e,a){e=L({timeout:45e3},e);var t=d.beforeRequest||E.Vhs.xhr.beforeRequest,i=d._requestCallbackSet||E.Vhs.xhr._requestCallbackSet||new Set;let o=d._responseCallbackSet||E.Vhs.xhr._responseCallbackSet;t&&"function"==typeof t&&(E.log.warn("beforeRequest is deprecated, use onRequest instead."),i.add(t));var s=(!0===E.Vhs.xhr.original?E:E.Vhs).xhr,r=((e,i)=>{if(e&&e.size){let t=i;return e.forEach(e=>{t=e(t)}),t}})(i,e);i.delete(t);let l=s(r||e,function(e,t){var i,s,r,n;return i=o,s=l,r=e,n=t,i&&i.size&&i.forEach(e=>{e(s,r,n)}),Mh(l,e,t,a)}),n=l.abort;return l.abort=function(){return l.aborted=!0,n.apply(l,arguments)},l.uri=e.uri,l.requestType=e.requestType,l.requestTime=Date.now(),l}return d.original=!0,d}function Bh(e){var t={};return e.byterange&&(t.Range=function(e){let t;return"bytes="+e.offset+"-"+(t="bigint"==typeof e.offset||"bigint"==typeof e.length?window.BigInt(e.offset)+window.BigInt(e.length)-window.BigInt(1):e.offset+e.length-1)}(e.byterange)),t}function Fh(e,t){return e=e.toString(16),"00".substring(0,2-e.length)+e+(t%2?" ":"")}function qh(e){return 32<=e&&e<126?String.fromCharCode(e):"."}function jh(e){var t=e.byterange||{length:1/0,offset:0};return[t.length,t.offset,e.resolvedUri].join(",")}function Vh(e){return e.resolvedUri}let Hh=function(i){let s={};return Object.keys(i).forEach(e=>{var t=i[e];pa(t)?s[e]={bytes:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength}:s[e]=t}),s},zh=e=>{var t,i,s=Array.prototype.slice.call(e);let r="";for(let e=0;ezh(e),textRanges:e=>{let t="",i;for(i=0;ie.transmuxedPresentationEnd-e.transmuxedPresentationStart-e.transmuxerPrependedSeconds,Gh=({playlist:e,time:t=void 0,callback:i})=>{var s,r;if(i)return e&&void 0!==t?(e=((t,i)=>{if(!i||!i.segments||0===i.segments.length)return null;let s=0,r;for(let e=0;es){if(t>s+e.duration*$h)return null;r=e}return{segment:r,estimatedStart:r.videoTimingInfo?r.videoTimingInfo.transmuxedPresentationStart:s-r.duration,type:r.videoTimingInfo?"accurate":"estimate"}})(t,e))?"estimate"===e.type?i({message:"Accurate programTime could not be determined. Please seek to e.seekTime and try again",seekTime:e.estimatedStart}):(s={mediaSeconds:t},t=t,(r=(e=e.segment).dateTimeObject?(r=e.videoTimingInfo.transmuxerPrependedSeconds,t=t-(e.videoTimingInfo.transmuxedPresentationStart+r),new Date(e.dateTimeObject.getTime()+1e3*t)):null)&&(s.programDateTime=r.toISOString()),i(null,s)):i({message:"valid programTime was not found"}):i({message:"getProgramTime: playlist and time must be provided"});throw new Error("getProgramTime: callback must be provided")},Xh=({programTime:e,playlist:t,retryCount:i=2,seekTo:s,pauseAfterSeek:r=!0,tech:n,callback:a})=>{var o,l,d;if(a)return"undefined"!=typeof e&&t&&s?t.endList||n.hasStarted_?(t=>{if(!t.segments||0===t.segments.length)return!1;for(let e=0;e{let i;try{i=new Date(e)}catch(e){return null}if(!t||!t.segments||0===t.segments.length)return null;let s=t.segments[0];if(ia?null:{segment:s=i>new Date(n)?e:s,estimatedStart:s.videoTimingInfo?s.videoTimingInfo.transmuxedPresentationStart:ph.duration(t,t.mediaSequence+t.segments.indexOf(s)),type:s.videoTimingInfo?"accurate":"estimate"}})(e,t))?(l=((e,t)=>{let i,s;try{i=new Date(e),s=new Date(t)}catch(e){}e=i.getTime();return(s.getTime()-e)/1e3})((o=d.segment).dateTimeObject,e),"estimate"===d.type?0===i?a({message:e+" is not buffered yet. Try again"}):(s(d.estimatedStart+l),void n.one("seeked",()=>{Xh({programTime:e,playlist:t,retryCount:i-1,seekTo:s,pauseAfterSeek:r,tech:n,callback:a})})):(d=o.start+l,n.one("seeked",()=>a(null,n.currentTime())),r&&n.pause(),void s(d))):a({message:e+" was not found in the stream"}):a({message:"programDateTime tags must be provided in the manifest "+t.resolvedUri}):a({message:"player must be playing a live stream to start buffering"}):a({message:"seekToProgramTime: programTime, seekTo and playlist must be provided"});throw new Error("seekToProgramTime: callback must be provided")},Kh=(e,t)=>{if(4===e.readyState)return t()},Yh=(e,t,r,s)=>{function n(e,t,i,s){return t.abort(),l=!0,r(e,t,i,s)}function i(e,t){var i;if(!l)return e?(e.metadata=Eh({requestType:s,request:t,error:e}),n(e,t,"",a)):(i=t.responseText.substring(a&&a.byteLength||0,t.responseText.length),a=function(){for(var e,t,i,s=arguments.length,r=new Array(s),n=0;nn(e,t,"",a)):n(null,t,i,a))}let a=[],o,l=!1;let d=t({uri:e,beforeSend(e){e.overrideMimeType("text/plain; charset=x-user-defined"),e.addEventListener("progress",function({}){return Mh(e,null,{statusCode:e.status},i)})}},function(e,t){return Mh(d,e,t,i)});return d};e=E.EventTarget;function Qh(t,i){if(!Ph(t,i))return!1;if(t.sidx&&i.sidx&&(t.sidx.offset!==i.sidx.offset||t.sidx.length!==i.sidx.length))return!1;if(!t.sidx&&i.sidx||t.sidx&&!i.sidx)return!1;if(t.segments&&!i.segments||!t.segments&&i.segments)return!1;if(t.segments||i.segments)for(let e=0;e{return`placeholder-uri-${e}-${t}-`+(s.attributes.NAME||i)},Zh=({mainXml:e,srcUrl:t,clientOffset:i,sidxMapping:s,previousManifest:r})=>{e=e,i={manifestUri:t,clientOffset:i,sidxMapping:s,previousManifest:r},e=ad(od(e),i),s=$l(e.representationInfo);r=Rl({dashPlaylists:s,locations:e.locations,contentSteering:e.contentSteeringInfo,sidxMapping:i.sidxMapping,previousManifest:i.previousManifest,eventStream:e.eventStream});return vh(r,t,Jh),r},eu=(e,t,i)=>{let a=!0,o=L(e,{duration:t.duration,minimumUpdatePeriod:t.minimumUpdatePeriod,timelineStarts:t.timelineStarts});for(let e=0;e{var r,n;e.playlists&&e.playlists.length&&(r=e.playlists[0].id,n=Lh(o,e.playlists[0],Qh))&&(s in(o=n).mediaGroups[t][i]||(o.mediaGroups[t][i][s]=e),o.mediaGroups[t][i][s].playlists[0]=o.playlists[r],a=!1)}),n=o,l=t,yh(n,(e,t,i,s)=>{l.mediaGroups[t][i]&&s in l.mediaGroups[t][i]||delete n.mediaGroups[t][i][s]}),(a=t.minimumUpdatePeriod===e.minimumUpdatePeriod&&a)?null:o},tu=(e,t)=>{return(Boolean(!e.map&&!t.map)||Boolean(e.map&&t.map&&e.map.byterange.offset===t.map.byterange.offset&&e.map.byterange.length===t.map.byterange.length))&&e.uri===t.uri&&e.byterange.offset===t.byterange.offset&&e.byterange.length===t.byterange.length},iu=(e,t)=>{var i,s={};for(i in e){var r=e[i].sidx;if(r){var n=vl(r);if(!t[n])break;var a=t[n].sidxInfo;tu(a,r)&&(s[n]=t[n])}}return s};class su extends e{constructor(e,t,i={},s){super(),this.isPaused_=!0,this.mainPlaylistLoader_=s||this,s||(this.isMain_=!0);var{withCredentials:s=!1}=i;if(this.vhs_=t,this.withCredentials=s,this.addMetadataToTextTrack=i.addMetadataToTextTrack,!e)throw new Error("A non-empty playlist URL or object is required");this.on("minimumUpdatePeriod",()=>{this.refreshXml_()}),this.on("mediaupdatetimeout",()=>{this.refreshMedia_(this.media().id)}),this.state="HAVE_NOTHING",this.loadedPlaylists_={},this.logger_=Bd("DashPlaylistLoader"),this.isMain_?(this.mainPlaylistLoader_.srcUrl=e,this.mainPlaylistLoader_.sidxMapping_={}):this.childPlaylist_=e}get isPaused(){return this.isPaused_}requestErrored_(e,t,i){return!this.request||(this.request=null,e?(this.error="object"!=typeof e||e instanceof Error?{status:t.status,message:"DASH request error at URL: "+t.uri,response:t.response,code:2,metadata:e.metadata}:e,i&&(this.state=i),this.trigger("error"),!0):void 0)}addSidxSegments_(l,r,n){let d=l.sidx&&vl(l.sidx);if(l.sidx&&d&&!this.mainPlaylistLoader_.sidxMapping_[d]){let a=Ud(l.sidx.resolvedUri),o=(t,i)=>{if(!this.requestErrored_(t,i,r)){var t=this.mainPlaylistLoader_.sidxMapping_,s=i.requestType;let e;try{e=gd(S(i.response).subarray(8))}catch(e){return e.metadata=Eh({requestType:s,request:i,parseFailure:!0}),void this.requestErrored_(e,i,r)}return t[d]={sidxInfo:l.sidx,sidx:e},hl(l,e,l.sidx.resolvedUri),n(!0)}};this.request=Yh(a,this.vhs_.xhr,(e,t,i,s)=>{var r,n;return e?o(e,t):i&&"mp4"===i?({offset:r,length:n}=l.sidx.byterange,s.length>=n+r?o(e,{response:s.subarray(r,r+n),status:t.status,uri:t.uri}):void(this.request=this.vhs_.xhr({uri:a,responseType:"arraybuffer",requestType:"dash-sidx",headers:Bh({byterange:l.sidx.byterange})},o))):(e=i||"unknown",o({status:t.status,message:`Unsupported ${e} container type for sidx segment at URL: `+a,response:"",playlist:l,internal:!0,playlistExclusionDuration:1/0,code:2},t))},"dash-sidx")}else window.clearTimeout(this.mediaRequest_),this.mediaRequest_=window.setTimeout(()=>n(!1),0)}dispose(){this.isPaused_=!0,this.trigger("dispose"),this.stopRequest(),this.loadedPlaylists_={},window.clearTimeout(this.minimumUpdatePeriodTimeout_),window.clearTimeout(this.mediaRequest_),window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null,this.mediaRequest_=null,this.minimumUpdatePeriodTimeout_=null,this.mainPlaylistLoader_.createMupOnMedia_&&(this.off("loadedmetadata",this.mainPlaylistLoader_.createMupOnMedia_),this.mainPlaylistLoader_.createMupOnMedia_=null),this.off()}hasPendingRequest(){return this.request||this.mediaRequest_}stopRequest(){var e;this.request&&(e=this.request,this.request=null,e.onreadystatechange=null,e.abort())}media(t){if(!t)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);let i=this.state;if("string"==typeof t){if(!this.mainPlaylistLoader_.main.playlists[t])throw new Error("Unknown playlist URI: "+t);t=this.mainPlaylistLoader_.main.playlists[t]}var e=!this.media_||t.id!==this.media_.id;e&&this.loadedPlaylists_[t.id]&&this.loadedPlaylists_[t.id].endList?(this.state="HAVE_METADATA",this.media_=t,e&&(this.trigger("mediachanging"),this.trigger("mediachange"))):e&&(this.media_&&this.trigger("mediachanging"),this.addSidxSegments_(t,i,e=>{this.haveMetadata({startingState:i,playlist:t})}))}haveMetadata({startingState:e,playlist:t}){this.state="HAVE_METADATA",this.loadedPlaylists_[t.id]=t,window.clearTimeout(this.mediaRequest_),this.mediaRequest_=null,this.refreshMedia_(t.id),"HAVE_MAIN_MANIFEST"===e?this.trigger("loadedmetadata"):this.trigger("mediachange")}pause(){this.isPaused_=!0,this.mainPlaylistLoader_.createMupOnMedia_&&(this.off("loadedmetadata",this.mainPlaylistLoader_.createMupOnMedia_),this.mainPlaylistLoader_.createMupOnMedia_=null),this.stopRequest(),window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null,this.isMain_&&(window.clearTimeout(this.mainPlaylistLoader_.minimumUpdatePeriodTimeout_),this.mainPlaylistLoader_.minimumUpdatePeriodTimeout_=null),"HAVE_NOTHING"===this.state&&(this.started=!1)}load(e){this.isPaused_=!1,window.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=null;var t=this.media();e?(e=t?t.targetDuration/2*1e3:5e3,this.mediaUpdateTimeout=window.setTimeout(()=>this.load(),e)):this.started?t&&!t.endList?(this.isMain_&&!this.minimumUpdatePeriodTimeout_&&(this.trigger("minimumUpdatePeriod"),this.updateMinimumUpdatePeriodTimeout_()),this.trigger("mediaupdatetimeout")):this.trigger("loadedplaylist"):this.start()}start(){this.started=!0,this.isMain_?this.requestMain_((e,t)=>{this.haveMain_(),this.hasPendingRequest()||this.media_||this.media(this.mainPlaylistLoader_.main.playlists[0])}):(window.clearTimeout(this.mediaRequest_),this.mediaRequest_=window.setTimeout(()=>this.haveMain_(),0))}requestMain_(s){let r={manifestInfo:{uri:this.mainPlaylistLoader_.srcUrl}};this.trigger({type:"manifestrequeststart",metadata:r}),this.request=this.vhs_.xhr({uri:this.mainPlaylistLoader_.srcUrl,withCredentials:this.withCredentials,requestType:"dash-manifest"},(e,t)=>{var i;if(e&&(i=t.requestType,e.metadata=Eh({requestType:i,request:t,error:e})),this.requestErrored_(e,t))"HAVE_NOTHING"===this.state&&(this.started=!1);else{this.trigger({type:"manifestrequestcomplete",metadata:r});let e=t.responseText!==this.mainPlaylistLoader_.mainXml_;if(this.mainPlaylistLoader_.mainXml_=t.responseText,t.responseHeaders&&t.responseHeaders.date?this.mainLoaded_=Date.parse(t.responseHeaders.date):this.mainLoaded_=Date.now(),this.mainPlaylistLoader_.srcUrl=Ud(this.mainPlaylistLoader_.srcUrl,t),!e)return s(t,e);this.handleMain_(),this.syncClientServerClock_(()=>s(t,e))}})}syncClientServerClock_(r){let n=ld(this.mainPlaylistLoader_.mainXml_);return null===n?(this.mainPlaylistLoader_.clientOffset_=this.mainLoaded_-Date.now(),r()):"DIRECT"===n.method?(this.mainPlaylistLoader_.clientOffset_=n.value-Date.now(),r()):void(this.request=this.vhs_.xhr({uri:Md(this.mainPlaylistLoader_.srcUrl,n.value),method:n.method,withCredentials:this.withCredentials,requestType:"dash-clock-sync"},(t,i)=>{if(this.request){var s;if(t)return s=i.requestType,this.error.metadata=Eh({requestType:s,request:i,error:t}),this.mainPlaylistLoader_.clientOffset_=this.mainLoaded_-Date.now(),r();let e;e="HEAD"===n.method?i.responseHeaders&&i.responseHeaders.date?Date.parse(i.responseHeaders.date):this.mainLoaded_:Date.parse(i.responseText),this.mainPlaylistLoader_.clientOffset_=e-Date.now(),r()}}))}haveMain_(){this.state="HAVE_MAIN_MANIFEST",this.isMain_?this.trigger("loadedplaylist"):this.media_||this.media(this.childPlaylist_)}handleMain_(){window.clearTimeout(this.mediaRequest_),this.mediaRequest_=null;var e=this.mainPlaylistLoader_.main,i={manifestInfo:{uri:this.mainPlaylistLoader_.srcUrl}};this.trigger({type:"manifestparsestart",metadata:i});let s;try{s=Zh({mainXml:this.mainPlaylistLoader_.mainXml_,srcUrl:this.mainPlaylistLoader_.srcUrl,clientOffset:this.mainPlaylistLoader_.clientOffset_,sidxMapping:this.mainPlaylistLoader_.sidxMapping_,previousManifest:e})}catch(e){this.error=e,this.error.metadata={errorType:E.Error.StreamingDashManifestParserError,error:e},this.trigger("error")}e&&(s=eu(e,s,this.mainPlaylistLoader_.sidxMapping_)),this.mainPlaylistLoader_.main=s||e;var r=this.mainPlaylistLoader_.main.locations&&this.mainPlaylistLoader_.main.locations[0];if(r&&r!==this.mainPlaylistLoader_.srcUrl&&(this.mainPlaylistLoader_.srcUrl=r),(!e||s&&s.minimumUpdatePeriod!==e.minimumUpdatePeriod)&&this.updateMinimumUpdatePeriodTimeout_(),this.addEventStreamToMetadataTrack_(s),s){var{duration:r,endList:e}=s;let t=[];s.playlists.forEach(e=>{t.push({id:e.id,bandwidth:e.attributes.BANDWIDTH,resolution:e.attributes.RESOLUTION,codecs:e.attributes.CODECS})});r={duration:r,isLive:!e,renditions:t};i.parsedManifest=r,this.trigger({type:"manifestparsecomplete",metadata:i})}return Boolean(s)}updateMinimumUpdatePeriodTimeout_(){var e=this.mainPlaylistLoader_;e.createMupOnMedia_&&(e.off("loadedmetadata",e.createMupOnMedia_),e.createMupOnMedia_=null),e.minimumUpdatePeriodTimeout_&&(window.clearTimeout(e.minimumUpdatePeriodTimeout_),e.minimumUpdatePeriodTimeout_=null);let t=e.main&&e.main.minimumUpdatePeriod;0===t&&(e.media()?t=1e3*e.media().targetDuration:(e.createMupOnMedia_=e.updateMinimumUpdatePeriodTimeout_,e.one("loadedmetadata",e.createMupOnMedia_))),"number"!=typeof t||t<=0?t<0&&this.logger_(`found invalid minimumUpdatePeriod of ${t}, not setting a timeout`):this.createMUPTimeout_(t)}createMUPTimeout_(e){let t=this.mainPlaylistLoader_;t.minimumUpdatePeriodTimeout_=window.setTimeout(()=>{t.minimumUpdatePeriodTimeout_=null,t.trigger("minimumUpdatePeriod"),t.createMUPTimeout_(e)},e)}refreshXml_(){this.requestMain_((e,t)=>{t&&(this.media_&&(this.media_=this.mainPlaylistLoader_.main.playlists[this.media_.id]),this.mainPlaylistLoader_.sidxMapping_=((e,r)=>{let n=iu(e.playlists,r);return yh(e,(e,t,i,s)=>{e.playlists&&e.playlists.length&&(e=e.playlists,n=L(n,iu(e,r)))}),n})(this.mainPlaylistLoader_.main,this.mainPlaylistLoader_.sidxMapping_),this.addSidxSegments_(this.media(),this.state,e=>{this.refreshMedia_(this.media().id)}))})}refreshMedia_(e){if(!e)throw new Error("refreshMedia_ must take a media id");this.media_&&this.isMain_&&this.handleMain_();var t=this.mainPlaylistLoader_.main.playlists;let i=!this.media_||this.media_!==t[e];if(i?this.media_=t[e]:this.trigger("playlistunchanged"),!this.mediaUpdateTimeout){let e=()=>{this.media().endList||(this.mediaUpdateTimeout=window.setTimeout(()=>{this.trigger("mediaupdatetimeout"),e()},Oh(this.media(),Boolean(i))))};e()}this.trigger("loadedplaylist")}addEventStreamToMetadataTrack_(e){e&&this.mainPlaylistLoader_.main.eventStream&&(e=this.mainPlaylistLoader_.main.eventStream.map(e=>({cueTime:e.start,frames:[{data:e.messageData}]})),this.addMetadataToTextTrack("EventStream",e,this.mainPlaylistLoader_.main.duration))}getKeyIdSet(e){if(e.contentProtection){var t,i=new Set;for(t in e.contentProtection){var s=e.contentProtection[t].attributes["cenc:default_KID"];s&&i.add(s.replace(/-/g,"").toLowerCase())}return i}}}var R={GOAL_BUFFER_LENGTH:30,MAX_GOAL_BUFFER_LENGTH:60,BACK_BUFFER_LENGTH:30,GOAL_BUFFER_LENGTH_RATE:1,INITIAL_BANDWIDTH:4194304,BANDWIDTH_VARIANCE:1.2,BUFFER_LOW_WATER_LINE:0,MAX_BUFFER_LOW_WATER_LINE:30,EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE:16,BUFFER_LOW_WATER_LINE_RATE:1,BUFFER_HIGH_WATER_LINE:30};function ru(e){return e.on=e.addEventListener,e.off=e.removeEventListener,e}let nu=t=>{var i=new Uint8Array(new ArrayBuffer(t.length));for(let e=0;e>>1,e.samplingfrequencyindex<<7|e.channelcount<<3,6,1,2]))},X=function(e){return l(d.hdlr,re[e])},G=function(e){var t=new Uint8Array([0,0,0,0,0,0,0,2,0,0,0,3,0,1,95,144,e.duration>>>24&255,e.duration>>>16&255,e.duration>>>8&255,255&e.duration,85,196,0,0]);return e.samplerate&&(t[12]=e.samplerate>>>24&255,t[13]=e.samplerate>>>16&255,t[14]=e.samplerate>>>8&255,t[15]=255&e.samplerate),l(d.mdhd,t)},W=function(e){return l(d.mdia,G(e),X(e.type),q(e))},F=function(e){return l(d.mfhd,new Uint8Array([0,0,0,0,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e]))},q=function(e){return l(d.minf,"video"===e.type?l(d.vmhd,ne):l(d.smhd,ae),M(),Y(e))},V=function(e){for(var t=e.length,i=[];t--;)i[t]=Z(e[t]);return l.apply(null,[d.mvex].concat(i))},H=function(e){e=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,2,0,1,95,144,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return l(d.mvhd,e)},K=function(e){for(var t,i=e.samples||[],s=new Uint8Array(4+i.length),r=0;r>>8),n.push(255&s[o].byteLength),n=n.concat(Array.prototype.slice.call(s[o]));for(o=0;o>>8),a.push(255&r[o].byteLength),a=a.concat(Array.prototype.slice.call(r[o]));return t=[d.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(65280&e.width)>>8,255&e.width,(65280&e.height)>>8,255&e.height,0,72,0,0,0,72,0,0,0,0,0,0,0,1,19,118,105,100,101,111,106,115,45,99,111,110,116,114,105,98,45,104,108,115,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),l(d.avcC,new Uint8Array([1,e.profileIdc,e.profileCompatibility,e.levelIdc,255].concat([s.length],n,[r.length],a))),l(d.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192]))],e.sarRatio&&(i=e.sarRatio[0],e=e.sarRatio[1],t.push(l(d.pasp,new Uint8Array([(4278190080&i)>>24,(16711680&i)>>16,(65280&i)>>8,255&i,(4278190080&e)>>24,(16711680&e)>>16,(65280&e)>>8,255&e])))),l.apply(null,t)},pe=function(e){return l(d.mp4a,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,(65280&e.channelcount)>>8,255&e.channelcount,(65280&e.samplesize)>>8,255&e.samplesize,0,0,0,0,(65280&e.samplerate)>>8,255&e.samplerate,0,0]),U(e))},$=function(e){e=new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,0,(4278190080&e.duration)>>24,(16711680&e.duration)>>16,(65280&e.duration)>>8,255&e.duration,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,(65280&e.width)>>8,255&e.width,0,0,(65280&e.height)>>8,255&e.height,0,0]);return l(d.tkhd,e)},J=function(e){var t,i=l(d.tfhd,new Uint8Array([0,0,0,58,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0])),s=Math.floor(e.baseMediaDecodeTime/ve),r=Math.floor(e.baseMediaDecodeTime%ve),s=l(d.tfdt,new Uint8Array([1,0,0,0,s>>>24&255,s>>>16&255,s>>>8&255,255&s,r>>>24&255,r>>>16&255,r>>>8&255,255&r]));return"audio"===e.type?(t=ee(e,92),l(d.traf,i,s,t)):(r=K(e),t=ee(e,r.length+92),l(d.traf,i,s,t,r))},z=function(e){return e.duration=e.duration||4294967295,l(d.trak,$(e),W(e))},Z=function(e){var t=new Uint8Array([0,0,0,0,(4278190080&e.id)>>24,(16711680&e.id)>>16,(65280&e.id)>>8,255&e.id,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return"video"!==e.type&&(t[t.length-1]=0),l(d.trex,t)},me=function(e,t){var i=0,s=0,r=0,n=0;return e.length&&(void 0!==e[0].duration&&(i=1),void 0!==e[0].size&&(s=2),void 0!==e[0].flags&&(r=4),void 0!==e[0].compositionTimeOffset)&&(n=8),[0,0,i|s|r|n,1,(4278190080&e.length)>>>24,(16711680&e.length)>>>16,(65280&e.length)>>>8,255&e.length,(4278190080&t)>>>24,(16711680&t)>>>16,(65280&t)>>>8,255&t]},ge=function(e,t){var i,s,r,n,a=e.samples||[];for(t+=20+16*a.length,e=me(a,t),(s=new Uint8Array(e.length+16*a.length)).set(e),i=e.length,n=0;n>>24,s[i++]=(16711680&r.duration)>>>16,s[i++]=(65280&r.duration)>>>8,s[i++]=255&r.duration,s[i++]=(4278190080&r.size)>>>24,s[i++]=(16711680&r.size)>>>16,s[i++]=(65280&r.size)>>>8,s[i++]=255&r.size,s[i++]=r.flags.isLeading<<2|r.flags.dependsOn,s[i++]=r.flags.isDependedOn<<6|r.flags.hasRedundancy<<4|r.flags.paddingValue<<1|r.flags.isNonSyncSample,s[i++]=61440&r.flags.degradationPriority,s[i++]=15&r.flags.degradationPriority,s[i++]=(4278190080&r.compositionTimeOffset)>>>24,s[i++]=(16711680&r.compositionTimeOffset)>>>16,s[i++]=(65280&r.compositionTimeOffset)>>>8,s[i++]=255&r.compositionTimeOffset;return l(d.trun,s)},fe=function(e,t){var i,s,r,n,a=e.samples||[];for(t+=20+8*a.length,e=me(a,t),(i=new Uint8Array(e.length+8*a.length)).set(e),s=e.length,n=0;n>>24,i[s++]=(16711680&r.duration)>>>16,i[s++]=(65280&r.duration)>>>8,i[s++]=255&r.duration,i[s++]=(4278190080&r.size)>>>24,i[s++]=(16711680&r.size)>>>16,i[s++]=(65280&r.size)>>>8,i[s++]=255&r.size;return l(d.trun,i)},ee=function(e,t){return("audio"===e.type?fe:ge)(e,t)};function be(e,t){var i=xe();return i.dataOffset=t,i.compositionTimeOffset=e.pts-e.dts,i.duration=e.duration,i.size=4*e.length,i.size+=e.byteLength,e.keyFrame&&(i.flags.dependsOn=2,i.flags.isNonSyncSample=0),i}function r(e){for(var t=[];e--;)t.push(0);return t}function n(e){e=e||{},n.prototype.init.call(this),this.parse708captions_="boolean"!=typeof e.parse708captions||e.parse708captions,this.captionPackets_=[],this.ccStreams_=[new m(0,0),new m(0,1),new m(1,0),new m(1,1)],this.parse708captions_&&(this.cc708Stream_=new p({captionServices:e.captionServices})),this.reset(),this.ccStreams_.forEach(function(e){e.on("data",this.trigger.bind(this,"data")),e.on("partialdone",this.trigger.bind(this,"partialdone")),e.on("done",this.trigger.bind(this,"done"))},this),this.parse708captions_&&(this.cc708Stream_.on("data",this.trigger.bind(this,"data")),this.cc708Stream_.on("partialdone",this.trigger.bind(this,"partialdone")),this.cc708Stream_.on("done",this.trigger.bind(this,"done")))}function Te(e){return 32<=e&&e<=127||160<=e&&e<=255}function a(e){this.windowNum=e,this.reset()}function Se(e,t,i){this.serviceNum=e,this.text="",this.currentWindow=new a(-1),this.windows=[],this.stream=i,"string"==typeof t&&this.createTextDecoder(t)}function we(e){return null===e?"":(e=qe[e]||e,String.fromCharCode(e))}function o(){for(var e=[],t=je+1;t--;)e.push({text:"",indent:0,offset:0});return e}function Ee(e,t){var i=1;for(t$e;)e+=i*ze;return e}function Ce(e){var t,i;Ce.prototype.init.call(this),this.type_=e||"shared",this.push=function(e){"metadata"===e.type?this.trigger("data",e):"shared"!==this.type_&&e.type!==this.type_||(void 0===i&&(i=e.dts),e.dts=Ee(e.dts,i),e.pts=Ee(e.pts,i),t=e.dts,this.trigger("data",e))},this.flush=function(){i=t,this.trigger("done")},this.endTimeline=function(){this.flush(),this.trigger("endedtimeline")},this.discontinuity=function(){t=i=void 0},this.reset=function(){this.discontinuity(),this.trigger("reset")}}var ke,Ie={ftyp:B=function(){return l(d.ftyp,te,ie,te,se)},mdat:function(e){return l(d.mdat,e)},moof:function(e,t){for(var i=[],s=t.length;s--;)i[s]=J(t[s]);return l.apply(null,[d.moof,F(e)].concat(i))},moov:j=function(e){for(var t=e.length,i=[];t--;)i[t]=z(e[t]);return l.apply(null,[d.moov,H(4294967295)].concat(i).concat(V(e)))},initSegment:function(e){var t=B(),e=j(e),i=new Uint8Array(t.byteLength+e.byteLength);return i.set(t),i.set(e,t.byteLength),i}},xe=function(){return{size:0,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0,degradationPriority:0,isNonSyncSample:1}}},Ae={groupNalsIntoFrames:function(e){var t,i,s=[],r=[];for(r.byteLength=0,r.nalCount=0,t=s.byteLength=r.duration=0;tMe.ONE_SECOND_IN_TS/2))){for(a=(a=Ne()[e.samplerate])||t[0].data,o=0;o=i?e:(t.minSegmentDts=1/0,e.filter(function(e){return e.dts>=i&&(t.minSegmentDts=Math.min(t.minSegmentDts,e.dts),t.minSegmentPts=t.minSegmentDts,!0)}))},generateSampleTable:function(e){for(var t=[],i=0;i=this.virtualRowCount&&"function"==typeof this.beforeRowOverflow&&this.beforeRowOverflow(e),0this.virtualRowCount;)this.rows.shift(),this.rowIdx--},a.prototype.isEmpty=function(){return 0===this.rows.length||1===this.rows.length&&""===this.rows[0]},a.prototype.addText=function(e){this.rows[this.rowIdx]+=e},a.prototype.backspace=function(){var e;this.isEmpty()||(e=this.rows[this.rowIdx],this.rows[this.rowIdx]=e.substr(0,e.length-1))},Se.prototype.init=function(e,t){this.startPts=e;for(var i=0;i<8;i++)this.windows[i]=new a(i),"function"==typeof t&&(this.windows[i].beforeRowOverflow=t)},Se.prototype.setCurrentWindow=function(e){this.currentWindow=this.windows[e]},Se.prototype.createTextDecoder=function(t){if("undefined"==typeof TextDecoder)this.stream.trigger("log",{level:"warn",message:"The `encoding` option is unsupported without TextDecoder support"});else try{this.textDecoder_=new TextDecoder(t)}catch(e){this.stream.trigger("log",{level:"warn",message:"TextDecoder could not be created with "+t+" encoding. "+e})}},function(e){e=e||{},p.prototype.init.call(this);var t,i=this,s=e.captionServices||{},r={};Object.keys(s).forEach(e=>{t=s[e],/^SERVICE/.test(e)&&(r[e]=t.encoding)}),this.serviceEncodings=r,this.current708Packet=null,this.services={},this.push=function(e){(3===e.type||null===i.current708Packet)&&i.new708Packet(),i.add708Bytes(e)}}),qe=(p.prototype=new c,p.prototype.new708Packet=function(){null!==this.current708Packet&&this.push708Packet(),this.current708Packet={data:[],ptsVals:[]}},p.prototype.add708Bytes=function(e){var t=e.ccData,i=t>>>8,t=255&t;this.current708Packet.ptsVals.push(e.pts),this.current708Packet.data.push(i),this.current708Packet.data.push(t)},p.prototype.push708Packet=function(){var e,t=this.current708Packet,i=t.data,s=null,r=0,n=i[r++];for(t.seq=n>>6,t.sizeCode=63&n;r>5)&&0("0"+(255&e).toString(16)).slice(-2)).join(""),String.fromCharCode(parseInt(n,16))):(t=Fe[r=a|o]||r,4096&r&&r===t?"":String.fromCharCode(t)),l.pendingNewLine&&!l.isEmpty()&&l.newLine(this.getPts(e)),l.pendingNewLine=!1,l.addText(i),e},p.prototype.multiByteCharacter=function(e,t){var i=this.current708Packet.data,s=i[e+1];return e=Te(s)&&Te(i[e+2])?this.handleText(++e,t,{isMultiByte:!0}):e},p.prototype.setCurrentWindow=function(e,t){var i=this.current708Packet.data[e];return t.setCurrentWindow(7&i),e},p.prototype.defineWindow=function(e,t){var i=this.current708Packet.data,s=i[e],t=(t.setCurrentWindow(7&s),t.currentWindow),s=i[++e];return t.visible=(32&s)>>5,t.rowLock=(16&s)>>4,t.columnLock=(8&s)>>3,t.priority=7&s,s=i[++e],t.relativePositioning=(128&s)>>7,t.anchorVertical=127&s,s=i[++e],t.anchorHorizontal=s,s=i[++e],t.anchorPoint=(240&s)>>4,t.rowCount=15&s,s=i[++e],t.columnCount=63&s,s=i[++e],t.windowStyle=(56&s)>>3,t.penStyle=7&s,t.virtualRowCount=t.rowCount+1,e},p.prototype.setWindowAttributes=function(e,t){var i=this.current708Packet.data,t=(i[e],t.currentWindow.winAttr),s=i[++e];return t.fillOpacity=(192&s)>>6,t.fillRed=(48&s)>>4,t.fillGreen=(12&s)>>2,t.fillBlue=3&s,s=i[++e],t.borderType=(192&s)>>6,t.borderRed=(48&s)>>4,t.borderGreen=(12&s)>>2,t.borderBlue=3&s,s=i[++e],t.borderType+=(128&s)>>5,t.wordWrap=(64&s)>>6,t.printDirection=(48&s)>>4,t.scrollDirection=(12&s)>>2,t.justify=3&s,s=i[++e],t.effectSpeed=(240&s)>>4,t.effectDirection=(12&s)>>2,t.displayEffect=3&s,e},p.prototype.flushDisplayed=function(e,t){for(var i=[],s=0;s<8;s++)t.windows[s].visible&&!t.windows[s].isEmpty()&&i.push(t.windows[s].getText());t.endPts=e,t.text=i.join("\n\n"),this.pushCaption(t),t.startPts=e},p.prototype.pushCaption=function(e){""!==e.text&&(this.trigger("data",{startPts:e.startPts,endPts:e.endPts,text:e.text,stream:"cc708_"+e.serviceNum}),e.text="",e.startPts=e.endPts)},p.prototype.displayWindows=function(e,t){var i=this.current708Packet.data[++e],s=this.getPts(e);this.flushDisplayed(s,t);for(var r=0;r<8;r++)i&1<>4,t.offset=(12&s)>>2,t.penSize=3&s,s=i[++e],t.italics=(128&s)>>7,t.underline=(64&s)>>6,t.edgeType=(56&s)>>3,t.fontStyle=7&s,e},p.prototype.setPenColor=function(e,t){var i=this.current708Packet.data,t=(i[e],t.currentWindow.penColor),s=i[++e];return t.fgOpacity=(192&s)>>6,t.fgRed=(48&s)>>4,t.fgGreen=(12&s)>>2,t.fgBlue=3&s,s=i[++e],t.bgOpacity=(192&s)>>6,t.bgRed=(48&s)>>4,t.bgGreen=(12&s)>>2,t.bgBlue=3&s,s=i[++e],t.edgeRed=(48&s)>>4,t.edgeGreen=(12&s)>>2,t.edgeBlue=3&s,e},p.prototype.setPenLocation=function(e,t){var i=this.current708Packet.data,s=(i[e],t.currentWindow.penLoc);return t.currentWindow.pendingNewLine=!0,t=i[++e],s.row=15&t,t=i[++e],s.column=63&t,e},p.prototype.reset=function(e,t){var i=this.getPts(e);return this.flushDisplayed(i,t),this.initService(t.serviceNum,e)},{42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,304:174,305:176,306:189,307:191,308:8482,309:162,310:163,311:9834,312:224,313:160,314:232,315:226,316:234,317:238,318:244,319:251,544:193,545:201,546:211,547:218,548:220,549:252,550:8216,551:161,552:42,553:39,554:8212,555:169,556:8480,557:8226,558:8220,559:8221,560:192,561:194,562:199,563:200,564:202,565:203,566:235,567:206,568:207,569:239,570:212,571:217,572:249,573:219,574:171,575:187,800:195,801:227,802:205,803:204,804:236,805:210,806:242,807:213,808:245,809:123,810:125,811:92,812:94,813:95,814:124,815:126,816:196,817:228,818:214,819:246,820:223,821:165,822:164,823:9474,824:197,825:229,826:216,827:248,828:9484,829:9488,830:9492,831:9496}),je=14,Ve=[4352,4384,4608,4640,5376,5408,5632,5664,5888,5920,4096,4864,4896,5120,5152],m=function(e,t){m.prototype.init.call(this),this.field_=e||0,this.dataChannel_=t||0,this.name_="CC"+(1+(this.field_<<1|this.dataChannel_)),this.setConstants(),this.reset(),this.push=function(e){var t,i,s,r,n=32639&e.ccData;n===this.lastControlCode_?this.lastControlCode_=null:(4096==(61440&n)?this.lastControlCode_=n:n!==this.PADDING_&&(this.lastControlCode_=null),t=n>>>8,i=255&n,n!==this.PADDING_&&(n===this.RESUME_CAPTION_LOADING_?this.mode_="popOn":n===this.END_OF_CAPTION_?(this.mode_="popOn",this.clearFormatting(e.pts),this.flushDisplayed(e.pts),r=this.displayed_,this.displayed_=this.nonDisplayed_,this.nonDisplayed_=r,this.startPts_=e.pts):n===this.ROLL_UP_2_ROWS_?(this.rollUpRows_=2,this.setRollUp(e.pts)):n===this.ROLL_UP_3_ROWS_?(this.rollUpRows_=3,this.setRollUp(e.pts)):n===this.ROLL_UP_4_ROWS_?(this.rollUpRows_=4,this.setRollUp(e.pts)):n===this.CARRIAGE_RETURN_?(this.clearFormatting(e.pts),this.flushDisplayed(e.pts),this.shiftRowsUp_(),this.startPts_=e.pts):n===this.BACKSPACE_?"popOn"===this.mode_?this.nonDisplayed_[this.row_].text=this.nonDisplayed_[this.row_].text.slice(0,-1):this.displayed_[this.row_].text=this.displayed_[this.row_].text.slice(0,-1):n===this.ERASE_DISPLAYED_MEMORY_?(this.flushDisplayed(e.pts),this.displayed_=o()):n===this.ERASE_NON_DISPLAYED_MEMORY_?this.nonDisplayed_=o():n===this.RESUME_DIRECT_CAPTIONING_?("paintOn"!==this.mode_&&(this.flushDisplayed(e.pts),this.displayed_=o()),this.mode_="paintOn",this.startPts_=e.pts):this.isSpecialCharacter(t,i)?(s=we((t=(3&t)<<8)|i),this[this.mode_](e.pts,s),this.column_++):this.isExtCharacter(t,i)?("popOn"===this.mode_?this.nonDisplayed_[this.row_].text=this.nonDisplayed_[this.row_].text.slice(0,-1):this.displayed_[this.row_].text=this.displayed_[this.row_].text.slice(0,-1),s=we((t=(3&t)<<8)|i),this[this.mode_](e.pts,s),this.column_++):this.isMidRowCode(t,i)?(this.clearFormatting(e.pts),this[this.mode_](e.pts," "),this.column_++,14==(14&i)&&this.addFormatting(e.pts,["i"]),1==(1&i)&&this.addFormatting(e.pts,["u"])):this.isOffsetControlCode(t,i)?(this.nonDisplayed_[this.row_].offset=r=3&i,this.column_+=r):this.isPAC(t,i)?(r=Ve.indexOf(7968&n),"rollUp"===this.mode_&&(r-this.rollUpRows_+1<0&&(r=this.rollUpRows_-1),this.setRollUp(e.pts,r)),r!==this.row_&&0<=r&&r<=14&&(this.clearFormatting(e.pts),this.row_=r),1&i&&-1===this.formatting_.indexOf("u")&&this.addFormatting(e.pts,["u"]),16==(16&n)&&(this.column_=4*(r=(14&n)>>1),this.nonDisplayed_[this.row_].indent+=r),this.isColorPAC(i)&&14==(14&i)&&this.addFormatting(e.pts,["i"])):this.isNormalChar(t)&&(0===i&&(i=null),s=we(t),s+=we(i),this[this.mode_](e.pts,s),this.column_+=s.length)))}},c=(m.prototype=new c,m.prototype.flushDisplayed=function(e){let i=e=>{this.trigger("log",{level:"warn",message:"Skipping a malformed 608 caption at index "+e+"."})},s=[];this.displayed_.forEach((e,t)=>{if(e&&e.text&&e.text.length){try{e.text=e.text.trim()}catch(e){i(t)}e.text.length&&s.push({text:e.text,line:t+1,position:10+Math.min(70,10*e.indent)+2.5*e.offset})}else null==e&&i(t)}),s.length&&this.trigger("data",{startPts:this.startPts_,endPts:e,content:s,stream:this.name_})},m.prototype.reset=function(){this.mode_="popOn",this.topRow_=0,this.startPts_=0,this.displayed_=o(),this.nonDisplayed_=o(),this.lastControlCode_=null,this.column_=0,this.row_=je,this.rollUpRows_=2,this.formatting_=[]},m.prototype.setConstants=function(){0===this.dataChannel_?(this.BASE_=16,this.EXT_=17,this.CONTROL_=(20|this.field_)<<8,this.OFFSET_=23):1===this.dataChannel_&&(this.BASE_=24,this.EXT_=25,this.CONTROL_=(28|this.field_)<<8,this.OFFSET_=31),this.PADDING_=0,this.RESUME_CAPTION_LOADING_=32|this.CONTROL_,this.END_OF_CAPTION_=47|this.CONTROL_,this.ROLL_UP_2_ROWS_=37|this.CONTROL_,this.ROLL_UP_3_ROWS_=38|this.CONTROL_,this.ROLL_UP_4_ROWS_=39|this.CONTROL_,this.CARRIAGE_RETURN_=45|this.CONTROL_,this.RESUME_DIRECT_CAPTIONING_=41|this.CONTROL_,this.BACKSPACE_=33|this.CONTROL_,this.ERASE_DISPLAYED_MEMORY_=44|this.CONTROL_,this.ERASE_NON_DISPLAYED_MEMORY_=46|this.CONTROL_},m.prototype.isSpecialCharacter=function(e,t){return e===this.EXT_&&48<=t&&t<=63},m.prototype.isExtCharacter=function(e,t){return(e===this.EXT_+1||e===this.EXT_+2)&&32<=t&&t<=63},m.prototype.isMidRowCode=function(e,t){return e===this.EXT_&&32<=t&&t<=47},m.prototype.isOffsetControlCode=function(e,t){return e===this.OFFSET_&&33<=t&&t<=35},m.prototype.isPAC=function(e,t){return e>=this.BASE_&&e"},"");this[this.mode_](e,t)},m.prototype.clearFormatting=function(e){var t;this.formatting_.length&&(t=this.formatting_.reverse().reduce(function(e,t){return e+""},""),this.formatting_=[],this[this.mode_](e,t))},m.prototype.popOn=function(e,t){var i=this.nonDisplayed_[this.row_].text;this.nonDisplayed_[this.row_].text=i+=t},m.prototype.rollUp=function(e,t){var i=this.displayed_[this.row_].text;this.displayed_[this.row_].text=i+=t},m.prototype.shiftRowsUp_=function(){for(var e=0;e{if(e)for(var s=i;s>>2,o.timeStamp=a=(a*=4)+(3&n[7]),void 0===t.pts&&void 0===t.dts&&(t.pts=o.timeStamp,t.dts=o.timeStamp),this.trigger("timestamp",o)),t.frames.push(o),(i=i+10+s)>>4&&(i+=e[i]+1),0===t.pid)t.type="pat",s(e.subarray(i),t),this.trigger("data",t);else if(t.pid===this.pmtPid)for(t.type="pmt",s(e.subarray(i),t),this.trigger("data",t);this.packetsWaitingForPmt.length;)this.processPes_.apply(this,this.packetsWaitingForPmt.shift());else void 0===this.programMapTable?this.packetsWaitingForPmt.push([e,i,t]):this.processPes_(e,i,t)},this.processPes_=function(e,t,i){i.pid===this.programMapTable.video?i.streamType=S.H264_STREAM_TYPE:i.pid===this.programMapTable.audio?i.streamType=S.ADTS_STREAM_TYPE:i.streamType=this.programMapTable["timed-metadata"][i.pid],i.type="pes",i.data=e.subarray(t),this.trigger("data",i)}}).prototype=new st,Ge.STREAM_TYPES={h264:27,adts:15},(Xe=function(){function s(e,t,i){var s,r=new Uint8Array(e.size),n={type:t},a=0,o=0;if(e.data.length&&!(e.size<9)){for(n.trackId=e.data[0].pid,a=0;a>>3,t.pts*=4,t.pts+=(6&e[13])>>>1,t.dts=t.pts,64&i)&&(t.dts=(14&e[14])<<27|(255&e[15])<<20|(254&e[16])<<12|(255&e[17])<<5|(254&e[18])>>>3,t.dts*=4,t.dts+=(6&e[18])>>>1),t.data=e.subarray(9+e[8]))};Xe.prototype.init.call(this),this.push=function(i){({pat:function(){},pes:function(){var e,t;switch(i.streamType){case S.H264_STREAM_TYPE:e=n,t="video";break;case S.ADTS_STREAM_TYPE:e=a,t="audio";break;case S.METADATA_STREAM_TYPE:e=o,t="timed-metadata";break;default:return}i.payloadUnitStartIndicator&&s(e,t,!0),e.data.push(i),e.size+=i.data.byteLength},pmt:function(){var e={type:"metadata",tracks:[]};null!==(t=i.programMapTable).video&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.video,codec:"avc",type:"video"}),null!==t.audio&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.audio,codec:"adts",type:"audio"}),r=!0,l.trigger("data",e)}})[i.type]()},this.reset=function(){n.size=0,n.data.length=0,a.size=0,a.data.length=0,this.trigger("reset")},this.flushStreams_=function(){s(n,"video"),s(a,"audio"),s(o,"timed-metadata")},this.flush=function(){var e;!r&&t&&(e={type:"metadata",tracks:[]},null!==t.video&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.video,codec:"avc",type:"video"}),null!==t.audio&&e.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+t.audio,codec:"adts",type:"audio"}),l.trigger("data",e)),r=!1,this.flushStreams_(),this.trigger("done")}}).prototype=new st,{PAT_PID:0,MP2T_PACKET_LENGTH:188,TransportPacketStream:rt,TransportParseStream:Ge,ElementaryStream:Xe,TimestampRolloverStream:g,CaptionStream:T.CaptionStream,Cea608Stream:T.Cea608Stream,Cea708Stream:T.Cea708Stream,MetadataStream:v});for(Ke in S)S.hasOwnProperty(Ke)&&(nt[Ke]=S[Ke]);var at,ot,st=nt,g=t,lt=u.ONE_SECOND_IN_TS,dt=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],ht=function(l){var d,h=0;ht.prototype.init.call(this),this.skipWarn_=function(e,t){this.trigger("log",{level:"warn",message:`adts skiping bytes ${e} to ${t} in frame ${h} outside syncword`})},this.push=function(e){var t,i,s,r,n,a,o=0;if(l||(h=0),"audio"===e.type){for(d&&d.length?(s=d,(d=new Uint8Array(s.byteLength+e.data.byteLength)).set(s),d.set(e.data,s.byteLength)):d=e.data;o+7>5,n=(r=1024*(1+(3&d[o+6])))*lt/dt[(60&d[o+2])>>>2],d.byteLength-o>>6&3),channelcount:(1&d[o+2])<<2|(192&d[o+3])>>>6,samplerate:dt[(60&d[o+2])>>>2],samplingfrequencyindex:(60&d[o+2])>>>2,samplesize:16,data:d.subarray(o+7+i,o+t)}),h++,o+=t}"number"==typeof a&&(this.skipWarn_(a,o),a=null),d=d.subarray(o)}},this.flush=function(){h=0,this.trigger("done")},this.reset=function(){d=void 0,this.trigger("reset")},this.endTimeline=function(){d=void 0,this.trigger("endedtimeline")}},T=(ht.prototype=new g,ht),v=t,ut=function(s){var r=s.byteLength,n=0,a=0;this.length=function(){return 8*r},this.bitsAvailable=function(){return 8*r+a},this.loadWord=function(){var e=s.byteLength-r,t=new Uint8Array(4),i=Math.min(4,r);if(0===i)throw new Error("no bytes available");t.set(s.subarray(e,e+i)),n=new DataView(t.buffer).getUint32(0),a=8*i,r-=i},this.skipBits=function(e){var t;e>>32-t;return 0<(a-=t)?n<<=t:0>>e))return n<<=e,a-=e,e;return this.loadWord(),e+this.skipLeadingZeros()},this.skipUnsignedExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.skipExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.readUnsignedExpGolomb=function(){var e=this.skipLeadingZeros();return this.readBits(e+1)-1},this.readExpGolomb=function(){var e=this.readUnsignedExpGolomb();return 1&e?1+e>>>1:-1*(e>>>1)},this.readBoolean=function(){return 1===this.readBits(1)},this.readUnsignedByte=function(){return this.readBits(8)},this.loadWord()},ct=function(){var s,r,n=0;ct.prototype.init.call(this),this.push=function(e){for(var t,i=(r=r?((t=new Uint8Array(r.byteLength+e.data.byteLength)).set(r),t.set(e.data,r.byteLength),t):e.data).byteLength;n>4?20+i:10+i},ft=function(e,t){return e.length-t<10||e[t]!=="I".charCodeAt(0)||e[t+1]!=="D".charCodeAt(0)||e[t+2]!=="3".charCodeAt(0)?t:(t+=gt(e,t),ft(e,t))},yt=function(e,t,i){for(var s="",r=t;r=t+2&&255==(255&e[t])&&240==(240&e[t+1])&&16==(22&e[t+1])},parseId3TagSize:gt,parseAdtsSize:function(e,t){var i=(224&e[t+5])>>5;return 6144&e[t+3]|e[t+4]<<3|i},parseType:function(e,t){return e[t]==="I".charCodeAt(0)&&e[t+1]==="D".charCodeAt(0)&&e[t+2]==="3".charCodeAt(0)?"timed-metadata":!0&e[t]&&240==(240&e[t+1])?"audio":null},parseSampleRate:function(e){for(var t=0;t+5>>2];t++}return null},parseAacTimestamp:function(e){var t,i=10;64&e[5]&&(i=(i+=4)+pt(e.subarray(10,14)));do{if((t=pt(e.subarray(i+4,i+8)))<1)return null;if("PRIV"===String.fromCharCode(e[i],e[i+1],e[i+2],e[i+3]))for(var s,r,n=e.subarray(i+10,i+t+10),a=0;a>>2,(r*=4)+(3&s[7]);break}}while((i=i+10+t)n.length)break;t={type:"timed-metadata",data:n.subarray(r,r+s)},this.trigger("data",t),r+=s}else if(255==(255&n[r])&&240==(240&n[r+1])){if(n.length-r<7)break;if(r+(s=vt.parseAdtsSize(n,r))>n.length)break;t={type:"audio",data:n.subarray(r,r+s),pts:a,dts:a},this.trigger("data",t),r+=s}else r++;n=0=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0))}if(this.videoTrack?(a=this.videoTrack.timelineStartInfo.pts,Ut.forEach(function(e){n.info[e]=this.videoTrack[e]},this)):this.audioTrack&&(a=this.audioTrack.timelineStartInfo.pts,Mt.forEach(function(e){n.info[e]=this.audioTrack[e]},this)),this.videoTrack||this.audioTrack){for(1===this.pendingTracks.length?n.type=this.pendingTracks[0].type:n.type="combined",this.emittedTracks+=this.pendingTracks.length,e=It.initSegment(this.pendingTracks),n.initSegment=new Uint8Array(e.byteLength),n.initSegment.set(e),n.data=new Uint8Array(this.pendingBytes),s=0;s=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0)},kt.prototype.setRemux=function(e){this.remuxTracks=e},(Ct=function(s){var r,n,a=this,i=!0;Ct.prototype.init.call(this),s=s||{},this.baseMediaDecodeTime=s.baseMediaDecodeTime||0,this.transmuxPipeline_={},this.setupAacPipeline=function(){var t={};(this.transmuxPipeline_=t).type="aac",t.metadataStream=new E.MetadataStream,t.aacStream=new Ot,t.audioTimestampRolloverStream=new E.TimestampRolloverStream("audio"),t.timedMetadataTimestampRolloverStream=new E.TimestampRolloverStream("timed-metadata"),t.adtsStream=new Pt,t.coalesceStream=new kt(s,t.metadataStream),t.headOfPipeline=t.aacStream,t.aacStream.pipe(t.audioTimestampRolloverStream).pipe(t.adtsStream),t.aacStream.pipe(t.timedMetadataTimestampRolloverStream).pipe(t.metadataStream).pipe(t.coalesceStream),t.metadataStream.on("timestamp",function(e){t.aacStream.setTimestamp(e.timeStamp)}),t.aacStream.on("data",function(e){"timed-metadata"!==e.type&&"audio"!==e.type||t.audioSegmentStream||(n=n||{timelineStartInfo:{baseMediaDecodeTime:a.baseMediaDecodeTime},codec:"adts",type:"audio"},t.coalesceStream.numberOfTracks++,t.audioSegmentStream=new Ft(n,s),t.audioSegmentStream.on("log",a.getLogTrigger_("audioSegmentStream")),t.audioSegmentStream.on("timingInfo",a.trigger.bind(a,"audioTimingInfo")),t.adtsStream.pipe(t.audioSegmentStream).pipe(t.coalesceStream),a.trigger("trackinfo",{hasAudio:!!n,hasVideo:!!r}))}),t.coalesceStream.on("data",this.trigger.bind(this,"data")),t.coalesceStream.on("done",this.trigger.bind(this,"done")),Tt(this,t)},this.setupTsPipeline=function(){var i={};(this.transmuxPipeline_=i).type="ts",i.metadataStream=new E.MetadataStream,i.packetStream=new E.TransportPacketStream,i.parseStream=new E.TransportParseStream,i.elementaryStream=new E.ElementaryStream,i.timestampRolloverStream=new E.TimestampRolloverStream,i.adtsStream=new Pt,i.h264Stream=new Lt,i.captionStream=new E.CaptionStream(s),i.coalesceStream=new kt(s,i.metadataStream),i.headOfPipeline=i.packetStream,i.packetStream.pipe(i.parseStream).pipe(i.elementaryStream).pipe(i.timestampRolloverStream),i.timestampRolloverStream.pipe(i.h264Stream),i.timestampRolloverStream.pipe(i.adtsStream),i.timestampRolloverStream.pipe(i.metadataStream).pipe(i.coalesceStream),i.h264Stream.pipe(i.captionStream).pipe(i.coalesceStream),i.elementaryStream.on("data",function(e){var t;if("metadata"===e.type){for(t=e.tracks.length;t--;)r||"video"!==e.tracks[t].type?n||"audio"!==e.tracks[t].type||((n=e.tracks[t]).timelineStartInfo.baseMediaDecodeTime=a.baseMediaDecodeTime):(r=e.tracks[t]).timelineStartInfo.baseMediaDecodeTime=a.baseMediaDecodeTime;r&&!i.videoSegmentStream&&(i.coalesceStream.numberOfTracks++,i.videoSegmentStream=new Et(r,s),i.videoSegmentStream.on("log",a.getLogTrigger_("videoSegmentStream")),i.videoSegmentStream.on("timelineStartInfo",function(e){n&&!s.keepOriginalTimestamps&&(n.timelineStartInfo=e,i.audioSegmentStream.setEarliestDts(e.dts-a.baseMediaDecodeTime))}),i.videoSegmentStream.on("processedGopsInfo",a.trigger.bind(a,"gopInfo")),i.videoSegmentStream.on("segmentTimingInfo",a.trigger.bind(a,"videoSegmentTimingInfo")),i.videoSegmentStream.on("baseMediaDecodeTime",function(e){n&&i.audioSegmentStream.setVideoBaseMediaDecodeTime(e)}),i.videoSegmentStream.on("timingInfo",a.trigger.bind(a,"videoTimingInfo")),i.h264Stream.pipe(i.videoSegmentStream).pipe(i.coalesceStream)),n&&!i.audioSegmentStream&&(i.coalesceStream.numberOfTracks++,i.audioSegmentStream=new Ft(n,s),i.audioSegmentStream.on("log",a.getLogTrigger_("audioSegmentStream")),i.audioSegmentStream.on("timingInfo",a.trigger.bind(a,"audioTimingInfo")),i.audioSegmentStream.on("segmentTimingInfo",a.trigger.bind(a,"audioSegmentTimingInfo")),i.adtsStream.pipe(i.audioSegmentStream).pipe(i.coalesceStream)),a.trigger("trackinfo",{hasAudio:!!n,hasVideo:!!r})}}),i.coalesceStream.on("data",this.trigger.bind(this,"data")),i.coalesceStream.on("id3Frame",function(e){e.dispatchType=i.metadataStream.dispatchType,a.trigger("id3Frame",e)}),i.coalesceStream.on("caption",this.trigger.bind(this,"caption")),i.coalesceStream.on("done",this.trigger.bind(this,"done")),Tt(this,i)},this.setBaseMediaDecodeTime=function(e){var t=this.transmuxPipeline_;s.keepOriginalTimestamps||(this.baseMediaDecodeTime=e),n&&(n.timelineStartInfo.dts=void 0,n.timelineStartInfo.pts=void 0,w.clearDtsInfo(n),t.audioTimestampRolloverStream)&&t.audioTimestampRolloverStream.discontinuity(),r&&(t.videoSegmentStream&&(t.videoSegmentStream.gopCache_=[]),r.timelineStartInfo.dts=void 0,r.timelineStartInfo.pts=void 0,w.clearDtsInfo(r),t.captionStream.reset()),t.timestampRolloverStream&&t.timestampRolloverStream.discontinuity()},this.setAudioAppendStart=function(e){n&&this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(e)},this.setRemux=function(e){var t=this.transmuxPipeline_;s.remux=e,t&&t.coalesceStream&&t.coalesceStream.setRemux(e)},this.alignGopsWith=function(e){r&&this.transmuxPipeline_.videoSegmentStream&&this.transmuxPipeline_.videoSegmentStream.alignGopsWith(e)},this.getLogTrigger_=function(t){var i=this;return function(e){e.stream=t,i.trigger("log",e)}},this.push=function(e){var t;i&&((t=Rt(e))&&"aac"!==this.transmuxPipeline_.type?this.setupAacPipeline():t||"ts"===this.transmuxPipeline_.type||this.setupTsPipeline(),i=!1),this.transmuxPipeline_.headOfPipeline.push(e)},this.flush=function(){i=!0,this.transmuxPipeline_.headOfPipeline.flush()},this.endTimeline=function(){this.transmuxPipeline_.headOfPipeline.endTimeline()},this.reset=function(){this.transmuxPipeline_.headOfPipeline&&this.transmuxPipeline_.headOfPipeline.reset()},this.resetCaptions=function(){this.transmuxPipeline_.captionStream&&this.transmuxPipeline_.captionStream.reset()}}).prototype=new _t;function qt(e){var t="";return(t+=String.fromCharCode(e[0]))+String.fromCharCode(e[1])+String.fromCharCode(e[2])+String.fromCharCode(e[3])}function jt(e,t){var i,s,r,n=[];if(!t.length)return null;for(i=0;i>>0},Pe=function(e){return("00"+e.toString(16)).slice(-2)},Wt=t,Gt=qt,Xt=t,Kt=i.getUint64,Yt=i.getUint64,Qt=function(e){return{isLeading:(12&e[0])>>>2,dependsOn:3&e[0],isDependedOn:(192&e[1])>>>6,hasRedundancy:(48&e[1])>>>4,paddingValue:(14&e[1])>>>1,isNonSyncSample:1&e[1],degradationPriority:e[2]<<8|e[3]}},Jt=i.getUint64,Zt=qt,k={avc1:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);return{dataReferenceIndex:t.getUint16(6),width:t.getUint16(24),height:t.getUint16(26),horizresolution:t.getUint16(28)+t.getUint16(30)/16,vertresolution:t.getUint16(32)+t.getUint16(34)/16,frameCount:t.getUint16(40),depth:t.getUint16(74),config:I(e.subarray(78,e.byteLength))}},avcC:function(e){for(var t,i,s=new DataView(e.buffer,e.byteOffset,e.byteLength),r={configurationVersion:e[0],avcProfileIndication:e[1],profileCompatibility:e[2],avcLevelIndication:e[3],lengthSizeMinusOne:3&e[4],sps:[],pps:[]},n=31&e[5],a=6,o=0;o>>2&63,bufferSize:e[13]<<16|e[14]<<8|e[15],maxBitrate:e[16]<<24|e[17]<<16|e[18]<<8|e[19],avgBitrate:e[20]<<24|e[21]<<16|e[22]<<8|e[23],decoderConfigDescriptor:{tag:e[24],length:e[25],audioObjectType:e[26]>>>3&31,samplingFrequencyIndex:(7&e[26])<<1|e[27]>>>7&1,channelConfiguration:e[27]>>>3&15}}}},ftyp:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={majorBrand:Zt(e.subarray(0,4)),minorVersion:t.getUint32(4),compatibleBrands:[]},s=8;sMALFORMED DATA");else switch(31&e[r]){case 1:s.push("slice_layer_without_partitioning_rbsp");break;case 5:s.push("slice_layer_without_partitioning_rbsp_idr");break;case 6:s.push("sei_rbsp");break;case 7:s.push("seq_parameter_set_rbsp");break;case 8:s.push("pic_parameter_set_rbsp");break;case 9:s.push("access_unit_delimiter_rbsp");break;default:s.push("UNKNOWN NAL - "+e[r]&31)}return s}(e)}},mdhd:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i=4,e={version:t.getUint8(0),flags:new Uint8Array(e.subarray(1,4)),language:""};return 1===e.version?(e.creationTime=C(t.getUint32(i+=4)),e.modificationTime=C(t.getUint32(i+=8)),e.timescale=t.getUint32(i+=4),e.duration=t.getUint32(i+=8)):(e.creationTime=C(t.getUint32(i)),e.modificationTime=C(t.getUint32(i+=4)),e.timescale=t.getUint32(i+=4),e.duration=t.getUint32(i+=4)),t=t.getUint16(i+=4),e.language+=String.fromCharCode(96+(t>>10)),e.language+=String.fromCharCode(96+((992&t)>>5)),e.language+=String.fromCharCode(96+(31&t)),e},mdia:function(e){return{boxes:I(e)}},mfhd:function(e){return{version:e[0],flags:new Uint8Array(e.subarray(1,4)),sequenceNumber:e[4]<<24|e[5]<<16|e[6]<<8|e[7]}},minf:function(e){return{boxes:I(e)}},mp4a:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength),t={dataReferenceIndex:t.getUint16(6),channelcount:t.getUint16(16),samplesize:t.getUint16(18),samplerate:t.getUint16(24)+t.getUint16(26)/65536};return 28>4,isDependedOn:(12&e[i])>>2,hasRedundancy:3&e[i]});return t},sidx:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),references:[],referenceId:t.getUint32(4),timescale:t.getUint32(8)},s=12,r=(0===i.version?(i.earliestPresentationTime=t.getUint32(s),i.firstOffset=t.getUint32(s+4),s+=8):(i.earliestPresentationTime=Yt(e.subarray(s)),i.firstOffset=Yt(e.subarray(s+8)),s+=16),t.getUint16(s+=2));for(s+=2;0>>7,referencedSize:2147483647&t.getUint32(s),subsegmentDuration:t.getUint32(s+4),startsWithSap:!!(128&e[s+8]),sapType:(112&e[s+8])>>>4,sapDeltaTime:268435455&t.getUint32(s+8)});return i},smhd:function(e){return{version:e[0],flags:new Uint8Array(e.subarray(1,4)),balance:e[4]+e[5]/256}},stbl:function(e){return{boxes:I(e)}},ctts:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:t.getUint8(0),flags:new Uint8Array(e.subarray(1,4)),compositionOffsets:[]},s=t.getUint32(4),r=8;s;r+=8,s--)i.compositionOffsets.push({sampleCount:t.getUint32(r),sampleOffset:t[0===i.version?"getUint32":"getInt32"](r+4)});return i},stss:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:t.getUint8(0),flags:new Uint8Array(e.subarray(1,4)),syncSamples:[]},s=t.getUint32(4),r=8;s;r+=4,s--)i.syncSamples.push(t.getUint32(r));return i},stco:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),chunkOffsets:[]},s=t.getUint32(4),r=8;s;r+=4,s--)i.chunkOffsets.push(t.getUint32(r));return i},stsc:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i=t.getUint32(4),s={version:e[0],flags:new Uint8Array(e.subarray(1,4)),sampleToChunks:[]},r=8;i;r+=12,i--)s.sampleToChunks.push({firstChunk:t.getUint32(r),samplesPerChunk:t.getUint32(r+4),sampleDescriptionIndex:t.getUint32(r+8)});return s},stsd:function(e){return{version:e[0],flags:new Uint8Array(e.subarray(1,4)),sampleDescriptions:I(e.subarray(8))}},stsz:function(e){for(var t=new DataView(e.buffer,e.byteOffset,e.byteLength),i={version:e[0],flags:new Uint8Array(e.subarray(1,4)),sampleSize:t.getUint32(4),entries:[]},s=12;s>6,sampleHasRedundancy:(48&e[21])>>4,samplePaddingValue:(14&e[21])>>1,sampleIsDifferenceSample:!!(1&e[21]),sampleDegradationPriority:t.getUint16(22)}},trun:zt,"url ":function(e){return{version:e[0],flags:new Uint8Array(e.subarray(1,4))}},vmhd:function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);return{version:e[0],flags:new Uint8Array(e.subarray(1,4)),graphicsmode:t.getUint16(4),opcolor:new Uint16Array([t.getUint16(6),t.getUint16(8),t.getUint16(10)])}}},I=function(e){for(var t,i,s,r,n,a=0,o=[],l=new ArrayBuffer(e.length),d=new Uint8Array(l),h=0;h":i+"<\n"+t.map(function(e){return r+" "+e}).join("\n")+"\n"+r+" >":i+"<>":i+JSON.stringify(e,null,2).split("\n").map(function(e,t){return 0===t?e:r+" "+e}).join("\n")}).join("\n")+(s.boxes?"\n"+ei(s.boxes,t+1):"")}).join("\n")},Le={inspect:I,textify:ei,parseType:Zt,findBox:jt,parseTraf:k.traf,parseTfdt:k.tfdt,parseHdlr:k.hdlr,parseTfhd:k.tfhd,parseTrun:k.trun,parseSidx:k.sidx},ti=function(e){for(var t=0,i=String.fromCharCode(e[t]),s="";"\0"!==i;)s+=i,t++,i=String.fromCharCode(e[t]);return s+=i},ii=i.getUint64,si=function(e){return void 0!==e||null!==e},st="undefined"!=typeof window?window:"undefined"!=typeof ye?ye:"undefined"!=typeof self?self:{},T=st,ri=t,ni=Pe,x=jt,A=qt,ai={parseEmsgBox:function(e){var t,i,s,r,n,a,o,l=4,d=e[0],h=(0===d?(l=(l+=(r=ti(e.subarray(l))).length)+(n=ti(e.subarray(l))).length,s=(h=new DataView(e.buffer)).getUint32(l),o=h.getUint32(l+=4),t=h.getUint32(l+=4),i=h.getUint32(l+=4),l+=4):1===d&&(s=(h=new DataView(e.buffer)).getUint32(l),a=ii(e.subarray(l+=4)),t=h.getUint32(l+=8),i=h.getUint32(l+=4),l=(l=(l+=4)+(r=ti(e.subarray(l))).length)+(n=ti(e.subarray(l))).length),{scheme_id_uri:r,value:n,timescale:s||1,presentation_time:a,presentation_time_delta:o,event_duration:t,id:i,message_data:new Uint8Array(e.subarray(l,e.byteLength))});return n="\0"!==(r=h).scheme_id_uri,a=0===(s=d)&&si(r.presentation_time_delta)&&n,o=1===s&&si(r.presentation_time)&&n,!(1>>2&63).replace(/^0/,"")):i.codec="mp4a.40.2"):i.codec=i.codec.toLowerCase()),x(e,["mdia","mdhd"])[0]);s&&(i.timescale=pi(s)),n.push(i)}),n},getTimescaleFromMediaHeader:pi,getEmsgID3:function(e,i=0){return x(e,["emsg"]).map(e=>{var e=ai.parseEmsgBox(new Uint8Array(e)),t=ci(e.message_data);return{cueTime:ai.scaleTime(e.presentation_time,e.timescale,e.presentation_time_delta,i),duration:ai.scaleTime(e.event_duration,e.timescale),frames:t}})}};let gi=Le.parseTrun,fi=mi.findBox;var yi=T,g={getMdatTrafPairs:function(e){var i=fi(e,["moof","traf"]),e=fi(e,["mdat"]),s=[];return e.forEach(function(e,t){t=i[t];s.push({mdat:e,traf:t})}),s},parseSamples:function(e,t,i){var s=t,r=i.defaultSampleDuration||0,n=i.defaultSampleSize||0,a=i.trackId,o=[];return e.forEach(function(e){e=gi(e).samples;e.forEach(function(e){void 0===e.duration&&(e.duration=r),void 0===e.size&&(e.size=n),e.trackId=a,e.dts=s,void 0===e.compositionTimeOffset&&(e.compositionTimeOffset=0),"bigint"==typeof s?(e.pts=s+yi.BigInt(e.compositionTimeOffset),s+=yi.BigInt(e.duration)):(e.pts=s+e.compositionTimeOffset,s+=e.duration)}),o=o.concat(e)}),o}},_i=Re.discardEmulationPreventionBytes,vi=c.CaptionStream,bi=jt,Ti=Vt,Si=Ht,{getMdatTrafPairs:wi,parseSamples:Ei}=g,Ci=function(e,t){for(var i=e,s=0;s>>4&&(t+=e[4]+1),t}function Mi(e){switch(e){case 5:return"slice_layer_without_partitioning_rbsp_idr";case 6:return"sei_rbsp";case 7:return"seq_parameter_set_rbsp";case 8:return"pic_parameter_set_rbsp";case 9:return"access_unit_delimiter_rbsp";default:return null}}var Ui=function(){let d=9e4;this.init=function(e){e=D(e,["moov","trak","mdia","mdhd"])[0];e&&(d=Di(e))},this.parseSegment=function(e){let l=[];e=Li(e);let n=0;return e.forEach(function(e){let i=e.mdat;var e=e.traf,s=D(e,["tfdt"])[0],r=D(e,["tfhd"])[0],e=D(e,["trun"]);if(s&&(s=Ai(s),n=s.baseMediaDecodeTime),e.length&&r){s=Pi(e,n,r);let t=0;s.forEach(function(a){let o=new TextDecoder("utf-8");var e=i.slice(t,t+a.size);D(e,["vtte"])[0]||D(e,["vttc"]).forEach(function(e){var t=D(e,["payl"])[0],e=D(e,["sttg"])[0],i=a.pts/d,s=(a.pts+a.duration)/d;let r,n;if(t)try{r=o.decode(t)}catch(e){}if(e)try{n=o.decode(e)}catch(e){}a.duration&&r&&l.push({cueText:r,start:i,end:s,settings:n})}),t+=a.size})}}),l}},Bi=He,Fi=He,P=Ye,L={},O=(L.ts={parseType:function(e,t){e=Oi(e);return 0===e?"pat":e===t?"pmt":t?"pes":null},parsePat:function(e){var t=Ri(e),i=4+Ni(e);return t&&(i+=e[i]+1),(31&e[i+10])<<8|e[i+11]},parsePmt:function(e){var t={},i=Ri(e),s=4+Ni(e);if(i&&(s+=e[s]+1),1&e[s+5]){for(var r=3+((15&e[s+1])<<8|e[s+2])-4,n=12+((15&e[s+10])<<8|e[s+11]);n=e.byteLength?null:(i=null,192&(s=e[t+7])&&((i={}).pts=(14&e[t+9])<<27|(255&e[t+10])<<20|(254&e[t+11])<<12|(255&e[t+12])<<5|(254&e[t+13])>>>3,i.pts*=4,i.pts+=(6&e[t+13])>>>1,i.dts=i.pts,64&s)&&(i.dts=(14&e[t+14])<<27|(255&e[t+15])<<20|(254&e[t+16])<<12|(255&e[t+17])<<5|(254&e[t+18])>>>3,i.dts*=4,i.dts+=(6&e[t+18])>>>1),i)},videoPacketContainsKeyFrame:function(e){for(var t=4+Ni(e),i=e.subarray(t),s=0,r=0,n=!1;re.length?s=!0:(null===a&&(t=e.subarray(l,l+o),a=L.aac.parseAacTimestamp(t)),l+=o);break;case"audio":e.length-l<7?s=!0:(o=L.aac.parseAdtsSize(e,l))>e.length?s=!0:(null===n&&(t=e.subarray(l,l+o),n=L.aac.parseSampleRate(t)),r++,l+=o);break;default:l++}if(s)return null}return null===n||null===a?null:{audio:[{type:"audio",dts:a,pts:a},{type:"audio",dts:a+1024*r*(i=O/n),pts:a+1024*r*i}]}}:function(e){var t,i={pid:null,table:null},s={};for(t in qi(e,i),i.table)if(i.table.hasOwnProperty(t))switch(i.table[t]){case Fi.H264_STREAM_TYPE:s.video=[],Vi(e,i,s),0===s.video.length&&delete s.video;break;case Fi.ADTS_STREAM_TYPE:s.audio=[],ji(e,i,s),0===s.audio.length&&delete s.audio}return s})(e);return e&&(e.audio||e.video)?(t=t,(i=e).audio&&i.audio.length&&("undefined"!=typeof(s=t)&&!isNaN(s)||(s=i.audio[0].dts),i.audio.forEach(function(e){e.dts=P(e.dts,s),e.pts=P(e.pts,s),e.dtsTime=e.dts/O,e.ptsTime=e.pts/O})),i.video&&i.video.length&&("undefined"!=typeof(r=t)&&!isNaN(r)||(r=i.video[0].dts),i.video.forEach(function(e){e.dts=P(e.dts,r),e.pts=P(e.pts,r),e.dtsTime=e.dts/O,e.ptsTime=e.pts/O}),i.firstKeyFrame)&&((t=i.firstKeyFrame).dts=P(t.dts,r),t.pts=P(t.pts,r),t.dtsTime=t.dts/O,t.ptsTime=t.pts/O),e):null};class zi{constructor(e,t){this.options=t||{},this.self=e,this.init()}init(){var i,e;this.transmuxer&&this.transmuxer.dispose(),this.transmuxer=new $t(this.options),i=this.self,(e=this.transmuxer).on("data",function(e){var t=e.initSegment,t=(e.initSegment={data:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength},e.data);e.data=t.buffer,i.postMessage({action:"data",segment:e,byteOffset:t.byteOffset,byteLength:t.byteLength},[e.data])}),e.on("done",function(e){i.postMessage({action:"done"})}),e.on("gopInfo",function(e){i.postMessage({action:"gopInfo",gopInfo:e})}),e.on("videoSegmentTimingInfo",function(e){var t={start:{decode:u.videoTsToSeconds(e.start.dts),presentation:u.videoTsToSeconds(e.start.pts)},end:{decode:u.videoTsToSeconds(e.end.dts),presentation:u.videoTsToSeconds(e.end.pts)},baseMediaDecodeTime:u.videoTsToSeconds(e.baseMediaDecodeTime)};e.prependedContentDuration&&(t.prependedContentDuration=u.videoTsToSeconds(e.prependedContentDuration)),i.postMessage({action:"videoSegmentTimingInfo",videoSegmentTimingInfo:t})}),e.on("audioSegmentTimingInfo",function(e){var t={start:{decode:u.videoTsToSeconds(e.start.dts),presentation:u.videoTsToSeconds(e.start.pts)},end:{decode:u.videoTsToSeconds(e.end.dts),presentation:u.videoTsToSeconds(e.end.pts)},baseMediaDecodeTime:u.videoTsToSeconds(e.baseMediaDecodeTime)};e.prependedContentDuration&&(t.prependedContentDuration=u.videoTsToSeconds(e.prependedContentDuration)),i.postMessage({action:"audioSegmentTimingInfo",audioSegmentTimingInfo:t})}),e.on("id3Frame",function(e){i.postMessage({action:"id3Frame",id3Frame:e})}),e.on("caption",function(e){i.postMessage({action:"caption",caption:e})}),e.on("trackinfo",function(e){i.postMessage({action:"trackinfo",trackInfo:e})}),e.on("audioTimingInfo",function(e){i.postMessage({action:"audioTimingInfo",audioTimingInfo:{start:u.videoTsToSeconds(e.start),end:u.videoTsToSeconds(e.end)}})}),e.on("videoTimingInfo",function(e){i.postMessage({action:"videoTimingInfo",videoTimingInfo:{start:u.videoTsToSeconds(e.start),end:u.videoTsToSeconds(e.end)}})}),e.on("log",function(e){i.postMessage({action:"log",log:e})})}pushMp4Captions(e){this.captionParser||(this.captionParser=new xi,this.captionParser.init());var t=new Uint8Array(e.data,e.byteOffset,e.byteLength),e=this.captionParser.parse(t,e.trackIds,e.timescales);this.self.postMessage({action:"mp4Captions",captions:e&&e.captions||[],logs:e&&e.logs||[],data:t.buffer},[t.buffer])}initMp4WebVttParser(e){this.webVttParser||(this.webVttParser=new Ui);e=new Uint8Array(e.data,e.byteOffset,e.byteLength);this.webVttParser.init(e)}getMp4WebVttText(e){this.webVttParser||(this.webVttParser=new Ui);var e=new Uint8Array(e.data,e.byteOffset,e.byteLength),t=this.webVttParser.parseSegment(e);this.self.postMessage({action:"getMp4WebVttText",mp4VttCues:t||[],data:e.buffer},[e.buffer])}probeMp4StartTime({timescales:e,data:t}){e=mi.startTime(e,t);this.self.postMessage({action:"probeMp4StartTime",startTime:e,data:t},[t.buffer])}probeMp4Tracks({data:e}){var t=mi.tracks(e);this.self.postMessage({action:"probeMp4Tracks",tracks:t,data:e},[e.buffer])}probeEmsgID3({data:e,offset:t}){t=mi.getEmsgID3(e,t);this.self.postMessage({action:"probeEmsgID3",id3Frames:t,emsgData:e},[e.buffer])}probeTs({data:e,baseStartTime:t}){t="number"!=typeof t||isNaN(t)?void 0:t*u.ONE_SECOND_IN_TS,t=Hi(e,t);let i=null;t&&((i={hasVideo:t.video&&2===t.video.length||!1,hasAudio:t.audio&&2===t.audio.length||!1}).hasVideo&&(i.videoStart=t.video[0].ptsTime),i.hasAudio)&&(i.audioStart=t.audio[0].ptsTime),this.self.postMessage({action:"probeTs",result:i,data:e},[e.buffer])}clearAllMp4Captions(){this.captionParser&&this.captionParser.clearAllCaptions()}clearParsedMp4Captions(){this.captionParser&&this.captionParser.clearParsedCaptions()}push(e){e=new Uint8Array(e.data,e.byteOffset,e.byteLength);this.transmuxer.push(e)}reset(){this.transmuxer.reset()}setTimestampOffset(e){e=e.timestampOffset||0;this.transmuxer.setBaseMediaDecodeTime(Math.round(u.secondsToVideoTs(e)))}setAudioAppendStart(e){this.transmuxer.setAudioAppendStart(Math.ceil(u.secondsToVideoTs(e.appendStart)))}setRemux(e){this.transmuxer.setRemux(e.remux)}flush(e){this.transmuxer.flush(),self.postMessage({action:"done",type:"transmuxed"})}endTimeline(){this.transmuxer.endTimeline(),self.postMessage({action:"endedtimeline",type:"transmuxed"})}alignGopsWith(e){this.transmuxer.alignGopsWith(e.gopsToAlignWith.slice())}}self.onmessage=function(e){"init"===e.data.action&&e.data.options?this.messageHandlers=new zi(self,e.data.options):(this.messageHandlers||(this.messageHandlers=new zi(self)),e.data&&e.data.action&&"init"!==e.data.action&&this.messageHandlers[e.data.action]&&this.messageHandlers[e.data.action](e.data))}})));let hu=(e,t,i)=>{var{type:s,initSegment:r,captions:n,captionStreams:a,metadata:o,videoFrameDtsTime:l,videoFramePtsTime:d}=e.data.segment,t=(t.buffer.push({captions:n,captionStreams:a,metadata:o}),e.data.segment.boxes||{data:e.data.segment.data}),n={type:s,data:new Uint8Array(t.data,t.data.byteOffset,t.data.byteLength),initSegment:new Uint8Array(r.data,r.byteOffset,r.byteLength)};"undefined"!=typeof l&&(n.videoFrameDtsTime=l),"undefined"!=typeof d&&(n.videoFramePtsTime=d),i(n)},uu=({transmuxedData:e,callback:t})=>{e.buffer=[],t(e)},cu=(e,t)=>{t.gopInfo=e.data.gopInfo},pu=t=>{let{transmuxer:i,bytes:e,audioAppendStart:s,gopsToAlignWith:r,remux:n,onData:a,onTrackInfo:o,onAudioTimingInfo:l,onVideoTimingInfo:d,onVideoSegmentTimingInfo:h,onAudioSegmentTimingInfo:u,onId3:c,onCaptions:p,onDone:m,onEndedTimeline:g,onTransmuxerLog:f,isEndOfTimeline:y,segment:_,triggerSegmentEventFn:v}=t,b={buffer:[]},T=y;var S,w;i.onmessage=e=>{i.currentTransmux!==t||("data"===e.data.action&&hu(e,b,a),"trackinfo"===e.data.action&&o(e.data.trackInfo),"gopInfo"===e.data.action&&cu(e,b),"audioTimingInfo"===e.data.action&&l(e.data.audioTimingInfo),"videoTimingInfo"===e.data.action&&d(e.data.videoTimingInfo),"videoSegmentTimingInfo"===e.data.action&&h(e.data.videoSegmentTimingInfo),"audioSegmentTimingInfo"===e.data.action&&u(e.data.audioSegmentTimingInfo),"id3Frame"===e.data.action&&c([e.data.id3Frame],e.data.id3Frame.dispatchType),"caption"===e.data.action&&p(e.data.caption),"endedtimeline"===e.data.action&&(T=!1,g()),"log"===e.data.action&&f(e.data.log),"transmuxed"!==e.data.type)||T||(i.onmessage=null,uu({transmuxedData:b,callback:m}),mu(i))},i.onerror=()=>{var e={message:"Received an error message from the transmuxer worker",metadata:{errorType:E.Error.StreamingFailedToTransmuxSegment,segmentInfo:ic({segment:_})}};m(null,e)},s&&i.postMessage({action:"setAudioAppendStart",appendStart:s}),Array.isArray(r)&&i.postMessage({action:"alignGopsWith",gopsToAlignWith:r}),"undefined"!=typeof n&&i.postMessage({action:"setRemux",remux:n}),e.byteLength&&(S=e instanceof ArrayBuffer?e:e.buffer,w=e instanceof ArrayBuffer?0:e.byteOffset,v({type:"segmenttransmuxingstart",segment:_}),i.postMessage({action:"push",data:S,byteOffset:w,byteLength:e.byteLength},[S])),y&&i.postMessage({action:"endTimeline"}),i.postMessage({action:"flush"})},mu=e=>{e.currentTransmux=null,e.transmuxQueue.length&&(e.currentTransmux=e.transmuxQueue.shift(),"function"==typeof e.currentTransmux?e.currentTransmux():pu(e.currentTransmux))},gu=(e,t)=>{e.postMessage({action:t}),mu(e)},fu=(e,t)=>{t.currentTransmux?t.transmuxQueue.push(gu.bind(null,t,e)):(t.currentTransmux=e,gu(t,e))};let yu=e=>{e.transmuxer.currentTransmux?e.transmuxer.transmuxQueue.push(e):(e.transmuxer.currentTransmux=e,pu(e))};var _u=e=>{fu("reset",e)},vu=(yu,e=>{let t=new du,i=(t.currentTransmux=null,t.transmuxQueue=[],t.terminate);return t.terminate=()=>(t.currentTransmux=null,t.transmuxQueue.length=0,i.call(t)),t.postMessage({action:"init",options:e}),t});function bu(e,t){return(e=e&&window.getComputedStyle(e))?e[t]:""}function Tu(e,t){let i,s;return i=(i=e.attributes.BANDWIDTH?e.attributes.BANDWIDTH:i)||window.Number.MAX_VALUE,s=(s=t.attributes.BANDWIDTH?t.attributes.BANDWIDTH:s)||window.Number.MAX_VALUE,i-s}let Su=function(t){let i=t.transmuxer,s=t.endAction||t.action,r=t.callback;var e,n=f({},t,{endAction:null,transmuxer:null,callback:null});let a=e=>{e.data.action===s&&(i.removeEventListener("message",a),e.data.data&&(e.data.data=new Uint8Array(e.data.data,t.byteOffset||0,t.byteLength||e.data.data.byteLength),t.data)&&(t.data=e.data.data),r(e.data))};i.addEventListener("message",a),t.data?(e=t.data instanceof ArrayBuffer,n.byteOffset=e?0:t.data.byteOffset,n.byteLength=t.data.byteLength,e=[e?t.data:t.data.buffer],i.postMessage(n,e)):i.postMessage(n)},wu={FAILURE:2,TIMEOUT:-101,ABORTED:-102},Eu="wvtt",Cu=e=>{e.forEach(e=>{e.abort()})},ku=e=>({bandwidth:e.bandwidth,bytesReceived:e.bytesReceived||0,roundTripTime:e.roundTripTime||0}),Iu=e=>{var t=e.target,t={bandwidth:1/0,bytesReceived:0,roundTripTime:Date.now()-t.requestTime||0};return t.bytesReceived=e.loaded,t.bandwidth=Math.floor(t.bytesReceived/t.roundTripTime*8*1e3),t},xu=(e,t)=>{var i=t.requestType,i=Eh({requestType:i,request:t,error:e});return t.timedout?{status:t.status,message:"HLS request timed-out at URL: "+t.uri,code:wu.TIMEOUT,xhr:t,metadata:i}:t.aborted?{status:t.status,message:"HLS request aborted at URL: "+t.uri,code:wu.ABORTED,xhr:t,metadata:i}:e?{status:t.status,message:"HLS request errored at URL: "+t.uri,code:wu.FAILURE,xhr:t,metadata:i}:"arraybuffer"===t.responseType&&0===t.response.byteLength?{status:t.status,message:"Empty HLS response at URL: "+t.uri,code:wu.FAILURE,xhr:t,metadata:i}:null},Au=(r,n,a,o)=>(e,t)=>{var i=t.response,e=xu(e,t);if(e)return a(e,r);if(16!==i.byteLength)return a({status:t.status,message:"Invalid HLS key at URL: "+t.uri,code:wu.FAILURE,xhr:t},r);var e=new DataView(i),s=new Uint32Array([e.getUint32(0),e.getUint32(4),e.getUint32(8),e.getUint32(12)]);for(let e=0;e{t===Eu&&e.transmuxer.postMessage({action:"initMp4WebVttParser",data:e.map.bytes})},Pu=(i,e,s)=>{e===Eu&&Su({action:"getMp4WebVttText",data:i.bytes,transmuxer:i.transmuxer,callback:({data:e,mp4VttCues:t})=>{i.bytes=e,s(null,i,{mp4VttCues:t})}})},Lu=(i,s)=>{var e,t=Od(i.map.bytes);if("mp4"!==t)return e=i.map.resolvedUri||i.map.uri,s({internal:!0,message:`Found unsupported ${t=t||"unknown"} container for initialization segment at URL: `+e,code:wu.FAILURE,metadata:{mediaType:t}});Su({action:"probeMp4Tracks",data:i.map.bytes,transmuxer:i.transmuxer,callback:({tracks:e,data:t})=>(i.map.bytes=t,e.forEach(function(e){i.map.tracks=i.map.tracks||{},i.map.tracks[e.type]||("number"==typeof(i.map.tracks[e.type]=e).id&&e.timescale&&(i.map.timescales=i.map.timescales||{},i.map.timescales[e.id]=e.timescale),"text"===e.type&&Du(i,e.codec))}),s(null))})},Ou=({segment:i,bytes:t,trackInfoFn:s,timingInfoFn:e,videoSegmentTimingInfoFn:r,audioSegmentTimingInfoFn:n,id3Fn:a,captionsFn:o,isEndOfTimeline:l,endedTimelineFn:d,dataFn:h,doneFn:u,onTransmuxerLog:c,triggerSegmentEventFn:p})=>{var m=i.map&&i.map.tracks||{};let g=Boolean(m.audio&&m.video),f=e.bind(null,i,"audio","start"),y=e.bind(null,i,"audio","end"),_=e.bind(null,i,"video","start"),v=e.bind(null,i,"video","end");Su({action:"probeTs",transmuxer:i.transmuxer,data:t,baseStartTime:i.baseStartTime,callback:e=>{i.bytes=t=e.data;e=e.result;e&&(s(i,{hasAudio:e.hasAudio,hasVideo:e.hasVideo,isMuxed:g}),s=null),yu({bytes:t,transmuxer:i.transmuxer,audioAppendStart:i.audioAppendStart,gopsToAlignWith:i.gopsToAlignWith,remux:g,onData:e=>{e.type="combined"===e.type?"video":e.type,h(i,e)},onTrackInfo:e=>{s&&(g&&(e.isMuxed=!0),s(i,e))},onAudioTimingInfo:e=>{f&&"undefined"!=typeof e.start&&(f(e.start),f=null),y&&"undefined"!=typeof e.end&&y(e.end)},onVideoTimingInfo:e=>{_&&"undefined"!=typeof e.start&&(_(e.start),_=null),v&&"undefined"!=typeof e.end&&v(e.end)},onVideoSegmentTimingInfo:e=>{var t={pts:{start:e.start.presentation,end:e.end.presentation},dts:{start:e.start.decode,end:e.end.decode}};p({type:"segmenttransmuxingtiminginfoavailable",segment:i,timingInfo:t}),r(e)},onAudioSegmentTimingInfo:e=>{var t={pts:{start:e.start.pts,end:e.end.pts},dts:{start:e.start.dts,end:e.end.dts}};p({type:"segmenttransmuxingtiminginfoavailable",segment:i,timingInfo:t}),n(e)},onId3:(e,t)=>{a(i,e,t)},onCaptions:e=>{o(i,[e])},isEndOfTimeline:l,onEndedTimeline:()=>{d()},onTransmuxerLog:c,onDone:(e,t)=>{u&&(e.type="combined"===e.type?"video":e.type,p({type:"segmenttransmuxingcomplete",segment:i}),u(t,i,e))},segment:i,triggerSegmentEventFn:p})}})},Ru=({segment:n,bytes:a,trackInfoFn:e,timingInfoFn:o,videoSegmentTimingInfoFn:t,audioSegmentTimingInfoFn:i,id3Fn:l,captionsFn:d,isEndOfTimeline:s,endedTimelineFn:r,dataFn:h,doneFn:u,onTransmuxerLog:c,triggerSegmentEventFn:p})=>{let m=new Uint8Array(a);if(Rd(m)){n.isFmp4=!0;let i=n.map.tracks;if(i.text&&(!i.audio||!i.video))return h(n,{data:m,type:"text"}),void Pu(n,i.text.codec,u);let s={isFmp4:!0,hasVideo:!!i.video,hasAudio:!!i.audio},r=(i.audio&&i.audio.codec&&"enca"!==i.audio.codec&&(s.audioCodec=i.audio.codec),i.video&&i.video.codec&&"encv"!==i.video.codec&&(s.videoCodec=i.video.codec),i.video&&i.audio&&(s.isMuxed=!0),e(n,s),(e,t)=>{h(n,{data:m,type:s.hasAudio&&!s.isMuxed?"audio":"video"}),t&&t.length&&l(n,t),e&&e.length&&d(n,e),u(null,n,{})});void Su({action:"probeMp4StartTime",timescales:n.map.timescales,data:m,transmuxer:n.transmuxer,callback:({data:e,startTime:t})=>{a=e.buffer,n.bytes=m=e,s.hasAudio&&!s.isMuxed&&o(n,"audio","start",t),s.hasVideo&&o(n,"video","start",t),Su({action:"probeEmsgID3",data:m,transmuxer:n.transmuxer,offset:t,callback:({emsgData:e,id3Frames:t})=>{a=e.buffer,n.bytes=m=e,i.video&&e.byteLength&&n.transmuxer?Su({action:"pushMp4Captions",endAction:"mp4Captions",transmuxer:n.transmuxer,data:m,timescales:n.map.timescales,trackIds:[i.video.id],callback:e=>{a=e.data.buffer,n.bytes=m=e.data,e.logs.forEach(function(e){c(L(e,{stream:"mp4CaptionParser"}))}),r(e.captions,t)}}):r(void 0,t)}})}})}else n.transmuxer?("undefined"==typeof n.container&&(n.container=Od(m)),"ts"!==n.container&&"aac"!==n.container?(e(n,{hasAudio:!1,hasVideo:!1}),u(null,n,{})):Ou({segment:n,bytes:a,trackInfoFn:e,timingInfoFn:o,videoSegmentTimingInfoFn:t,audioSegmentTimingInfoFn:i,id3Fn:l,captionsFn:d,isEndOfTimeline:s,endedTimelineFn:r,dataFn:h,doneFn:u,onTransmuxerLog:c,triggerSegmentEventFn:p})):u(null,n,{})},Nu=function({id:t,key:e,encryptedBytes:i,decryptionWorker:s,segment:r,doneFn:n},a){let o=e=>{e.data.source===t&&(s.removeEventListener("message",o),e=e.data.decrypted,a(new Uint8Array(e.bytes,e.byteOffset,e.byteLength)))};s.onerror=()=>{var e="An error occurred in the decryption worker",t=ic({segment:r}),e={message:e,metadata:{error:new Error(e),errorType:E.Error.StreamingFailedToDecryptSegment,segmentInfo:t,keyInfo:{uri:r.key.resolvedUri||r.map.key.resolvedUri}}};n(e,r)},s.addEventListener("message",o);let l;l=e.bytes.slice?e.bytes.slice():new Uint32Array(Array.prototype.slice.call(e.bytes)),s.postMessage(Hh({source:t,encrypted:i,key:l,iv:e.iv}),[i.buffer,l.buffer])},Mu=({decryptionWorker:e,segment:t,trackInfoFn:i,timingInfoFn:s,videoSegmentTimingInfoFn:r,audioSegmentTimingInfoFn:n,id3Fn:a,captionsFn:o,isEndOfTimeline:l,endedTimelineFn:d,dataFn:h,doneFn:u,onTransmuxerLog:c,triggerSegmentEventFn:p})=>{p({type:"segmentdecryptionstart"}),Nu({id:t.requestId,key:t.key,encryptedBytes:t.encryptedBytes,decryptionWorker:e,segment:t,doneFn:u},e=>{t.bytes=e,p({type:"segmentdecryptioncomplete",segment:t}),Ru({segment:t,bytes:t.bytes,trackInfoFn:i,timingInfoFn:s,videoSegmentTimingInfoFn:r,audioSegmentTimingInfoFn:n,id3Fn:a,captionsFn:o,isEndOfTimeline:l,endedTimelineFn:d,dataFn:h,doneFn:u,onTransmuxerLog:c,triggerSegmentEventFn:p})})},Uu=({xhr:e,xhrOptions:t,decryptionWorker:i,segment:s,abortFn:r,progressFn:n,trackInfoFn:a,timingInfoFn:o,videoSegmentTimingInfoFn:l,audioSegmentTimingInfoFn:d,id3Fn:h,captionsFn:u,isEndOfTimeline:c,endedTimelineFn:p,dataFn:m,doneFn:g,onTransmuxerLog:f,triggerSegmentEventFn:y})=>{let _=[];var v,b,T,S,w,E,C,k,I,i=(({activeXhrs:s,decryptionWorker:r,trackInfoFn:n,timingInfoFn:a,videoSegmentTimingInfoFn:o,audioSegmentTimingInfoFn:l,id3Fn:d,captionsFn:h,isEndOfTimeline:u,endedTimelineFn:c,dataFn:p,doneFn:m,onTransmuxerLog:g,triggerSegmentEventFn:f})=>{let t=0,y=!1;return(e,i)=>{if(!y){if(e)return y=!0,Cu(s),m(e,i);if((t+=1)===s.length){let t=function(){if(i.encryptedBytes)return Mu({decryptionWorker:r,segment:i,trackInfoFn:n,timingInfoFn:a,videoSegmentTimingInfoFn:o,audioSegmentTimingInfoFn:l,id3Fn:d,captionsFn:h,isEndOfTimeline:u,endedTimelineFn:c,dataFn:p,doneFn:m,onTransmuxerLog:g,triggerSegmentEventFn:f});Ru({segment:i,bytes:i.bytes,trackInfoFn:n,timingInfoFn:a,videoSegmentTimingInfoFn:o,audioSegmentTimingInfoFn:l,id3Fn:d,captionsFn:h,isEndOfTimeline:u,endedTimelineFn:c,dataFn:p,doneFn:m,onTransmuxerLog:g,triggerSegmentEventFn:f})};if(i.endOfAllRequests=Date.now(),i.map&&i.map.encryptedBytes&&!i.map.bytes)return f({type:"segmentdecryptionstart",segment:i}),Nu({decryptionWorker:r,id:i.requestId+"-init",encryptedBytes:i.map.encryptedBytes,key:i.map.key,segment:i,doneFn:m},e=>{i.map.bytes=e,f({type:"segmentdecryptioncomplete",segment:i}),Lu(i,e=>{if(e)return Cu(s),m(e,i);t()})});t()}}}})({activeXhrs:_,decryptionWorker:i,trackInfoFn:a,timingInfoFn:o,videoSegmentTimingInfoFn:l,audioSegmentTimingInfoFn:d,id3Fn:h,captionsFn:u,isEndOfTimeline:c,endedTimelineFn:p,dataFn:m,doneFn:g,onTransmuxerLog:f,triggerSegmentEventFn:y}),f=(s.key&&!s.key.bytes&&(a=[s.key],s.map&&!s.map.bytes&&s.map.key&&s.map.key.resolvedUri===s.key.resolvedUri&&a.push(s.map.key),o=L(t,{uri:s.key.resolvedUri,responseType:"arraybuffer",requestType:"segment-key"}),l=Au(s,a,i,y),y({type:"segmentkeyloadstart",segment:s,keyInfo:{uri:s.key.resolvedUri}}),d=e(o,l),_.push(d)),s.map&&!s.map.bytes&&(!s.map.key||s.key&&s.key.resolvedUri===s.map.key.resolvedUri||(h=L(t,{uri:s.map.key.resolvedUri,responseType:"arraybuffer",requestType:"segment-key"}),u=Au(s,[s.map.key],i,y),y({type:"segmentkeyloadstart",segment:s,keyInfo:{uri:s.map.key.resolvedUri}}),c=e(h,u),_.push(c)),p=L(t,{uri:s.map.resolvedUri,responseType:"arraybuffer",headers:Bh(s.map),requestType:"segment-media-initialization"}),{segment:v,finishProcessingFn:b,triggerSegmentEventFn:T}=[{segment:s,finishProcessingFn:i,triggerSegmentEventFn:y}][0],m=(e,t)=>{var e=xu(e,t);return e?b(e,v):(e=new Uint8Array(t.response),T({type:"segmentloaded",segment:v}),v.map.key?(v.map.encryptedBytes=e,b(null,v)):(v.map.bytes=e,void Lu(v,function(e){if(e)return e.xhr=t,e.status=t.status,b(e,v);b(null,v)})))},y({type:"segmentloadstart",segment:s}),g=e(p,m),_.push(g)),L(t,{uri:s.part&&s.part.resolvedUri||s.resolvedUri,responseType:"arraybuffer",headers:Bh(s),requestType:"segment"})),a=({segment:S,finishProcessingFn:w,responseType:E,triggerSegmentEventFn:C}=[{segment:s,finishProcessingFn:i,responseType:f.responseType,triggerSegmentEventFn:y}][0],(e,t)=>{e=xu(e,t);if(e)return w(e,S);C({type:"segmentloaded",segment:S});e="arraybuffer"!==E&&t.responseText?nu(t.responseText.substring(S.lastReachedChar||0)):t.response;return S.stats=ku(t),S.key?S.encryptedBytes=new Uint8Array(e):S.bytes=new Uint8Array(e),w(null,S)}),o=(y({type:"segmentloadstart",segment:s}),e(f,a));o.addEventListener("progress",({segment:k,progressFn:I}=[{segment:s,progressFn:n}][0],e=>{var t=e.target;if(!t.aborted)return k.stats=L(k.stats,Iu(e)),!k.stats.firstBytesReceivedAt&&k.stats.bytesReceived&&(k.stats.firstBytesReceivedAt=Date.now()),I(e,k)})),_.push(o);let x={};return _.forEach(e=>{var t,i;e.addEventListener("loadend",({loadendState:t,abortFn:i}=[{loadendState:x,abortFn:r}][0],e=>{e.target.aborted&&i&&!t.calledAbortFn&&(i(),t.calledAbortFn=!0)}))}),()=>Cu(_)},Bu=Bd("PlaylistSelector"),Fu=function(e){var t;if(e&&e.playlist)return t=e.playlist,JSON.stringify({id:t.id,bandwidth:e.bandwidth,width:e.width,height:e.height,codecs:t.attributes&&t.attributes.CODECS||""})},qu=function(e,s){let r=e.slice();e.sort(function(e,t){var i=s(e,t);return 0===i?r.indexOf(e)-r.indexOf(t):i})};function ju(l){let{main:t,bandwidth:i,playerWidth:d,playerHeight:h,playerObjectFit:u,limitRenditionByPlayerDimensions:s,playlistController:c}=l;if(t){l={bandwidth:i,width:d,height:h,limitRenditionByPlayerDimensions:s};let e=t.playlists,n=(ph.isAudioOnly(t)&&(e=c.getAudioTrackPlaylists_(),l.audioOnly=!0),e.map(e=>{var t=e.attributes&&e.attributes.RESOLUTION&&e.attributes.RESOLUTION.width,i=e.attributes&&e.attributes.RESOLUTION&&e.attributes.RESOLUTION.height,s=e.attributes&&e.attributes.BANDWIDTH;return{bandwidth:s||window.Number.MAX_VALUE,width:t,height:i,playlist:e}})),a=(qu(n,(e,t)=>e.bandwidth-t.bandwidth),(n=n.filter(e=>!ph.isIncompatible(e.playlist))).filter(e=>ph.isEnabled(e.playlist)));var p=(a=a.length?a:n.filter(e=>!ph.isDisabled(e.playlist))).filter(e=>e.bandwidth*R.BANDWIDTH_VARIANCEe.bandwidth===o.bandwidth)[0];if(!1===s){let t=m||a[0]||n[0];if(t&&t.playlist){let e=m?"bandwidthBestRep":"sortedPlaylistReps";return a[0]&&(e="enabledPlaylistReps"),Bu(`choosing ${Fu(t)} using ${e} with options`,l),t.playlist}}else{var g,p=p.filter(e=>e.width&&e.height),f=(qu(p,(e,t)=>e.width-t.width),p.filter(e=>e.width===d&&e.height===h)),f=(o=f[f.length-1],f.filter(e=>e.bandwidth===o.bandwidth)[0]);let t,i;f||(g=(t=p.filter(e=>"cover"===u?e.width>d&&e.height>h:e.width>d||e.height>h)).filter(e=>e.width===t[0].width&&e.height===t[0].height),o=g[g.length-1],i=g.filter(e=>e.bandwidth===o.bandwidth)[0]);let s,r=(c.leastPixelDiffSelector&&(g=p.map(e=>(e.pixelDiff=Math.abs(e.width-d)+Math.abs(e.height-h),e)),qu(g,(e,t)=>e.pixelDiff===t.pixelDiff?t.bandwidth-e.bandwidth:e.pixelDiff-t.pixelDiff),s=g[0]),s||i||f||m||a[0]||n[0]);if(r&&r.playlist){let e="sortedPlaylistReps";return s?e="leastPixelDiffRep":i?e="resolutionPlusOneRep":f?e="resolutionBestRep":m?e="bandwidthBestRep":a[0]&&(e="enabledPlaylistReps"),Bu(`choosing ${Fu(r)} using ${e} with options`,l),r.playlist}}return Bu("could not choose a playlist with options",l),null}}function Vu(){let e=this.useDevicePixelRatio&&window.devicePixelRatio||1;return isNaN(this.customPixelRatio)||(e=this.customPixelRatio),ju({main:this.playlists.main,bandwidth:this.systemBandwidth,playerWidth:parseInt(bu(this.tech_.el(),"width"),10)*e,playerHeight:parseInt(bu(this.tech_.el(),"height"),10)*e,playerObjectFit:this.usePlayerObjectFit?bu(this.tech_.el(),"objectFit"):"",limitRenditionByPlayerDimensions:this.limitRenditionByPlayerDimensions,playlistController:this.playlistController_})}function Hu(e){try{return new URL(e).pathname.split("/").slice(-2).join("/")}catch(e){return""}}function zu(e,t,i){let s;var r;if(i&&i.cues)for(s=i.cues.length;s--;)(r=i.cues[s]).startTime>=e&&r.endTime<=t&&i.removeCue(r)}let $u=({inbandTextTracks:e,metadataArray:t,timestampOffset:i,videoDuration:o})=>{if(t){let r=window.WebKitDataCue||window.VTTCue,a=e.metadataTrack_;if(a&&(t.forEach(e=>{let s=e.cueTime+i;!("number"!=typeof s||window.isNaN(s)||s<0)&&s<1/0&&e.frames&&e.frames.length&&e.frames.forEach(e=>{var t,i=new r(s,s,e.value||e.url||e.data||"");i.frame=e,i.value=e,t=i,Object.defineProperties(t.frame,{id:{get(){return E.log.warn("cue.frame.id is deprecated. Use cue.value.key instead."),t.value.key}},value:{get(){return E.log.warn("cue.frame.value is deprecated. Use cue.value.data instead."),t.value.data}},privateData:{get(){return E.log.warn("cue.frame.privateData is deprecated. Use cue.value.data instead."),t.value.data}}}),a.addCue(i)})}),a.cues)&&a.cues.length){var s=a.cues,l=[];for(let e=0;e{var i=e[t.startTime]||[];return i.push(t),e[t.startTime]=i,e},{}),n=Object.keys(r).sort((e,t)=>Number(e)-Number(t));n.forEach((e,t)=>{var i=r[e],e=isFinite(o)?o:e;let s=Number(n[t+1])||e;i.forEach(e=>{e.endTime=s})})}}},Wu={id:"ID",class:"CLASS",startDate:"START-DATE",duration:"DURATION",endDate:"END-DATE",endOnNext:"END-ON-NEXT",plannedDuration:"PLANNED-DURATION",scte35Out:"SCTE35-OUT",scte35In:"SCTE35-IN"},Gu=new Set(["id","class","startDate","duration","endDate","endOnNext","startTime","endTime","processDateRange"]),Xu=(e,t,i)=>{e.metadataTrack_||(e.metadataTrack_=i.addRemoteTextTrack({kind:"metadata",label:"Timed Metadata"},!1).track,E.browser.IS_ANY_SAFARI)||(e.metadataTrack_.inBandMetadataTrackDispatchType=t)},Ku=e=>"number"==typeof e&&isFinite(e),Yu=e=>{var{startOfSegment:t,duration:i,segment:s,part:r,playlist:{mediaSequence:n,id:a,segments:o=[]},mediaIndex:l,partIndex:d,timeline:h}=e,o=o.length-1;let u="mediaIndex/partIndex increment";e.getMediaInfoForTime?u=`getMediaInfoForTime (${e.getMediaInfoForTime})`:e.isSyncRequest&&(u="getSyncSegmentCandidate (isSyncRequest)"),e.independent&&(u+=" with independent "+e.independent);var c="number"==typeof d,e=e.segment.uri?"segment":"pre-segment",p=c?Zd({preloadSegment:s})-1:0;return e+` [${n+l}/${n+o}]`+(c?` part [${d}/${p}]`:"")+` segment start/end [${s.start} => ${s.end}]`+(c?` part start/end [${r.start} => ${r.end}]`:"")+` startOfSegment [${t}]`+` duration [${i}]`+` timeline [${h}]`+` selected by [${u}]`+` playlist [${a}]`},Qu=e=>e+"TimingInfo",Ju=({timelineChangeController:e,currentTimeline:t,segmentTimeline:i,loaderType:s,audioDisabled:r})=>{return!(t===i||("audio"===s?(t=e.lastTimelineChange({type:"main"}))&&t.to===i:"main"!==s||!r||(t=e.pendingTimelineChange({type:"audio"}))&&t.to===i))},Zu=e=>{var t,i,s,r=e.pendingSegment_;r&&Ju({timelineChangeController:e.timelineChangeController_,currentTimeline:e.currentTimeline_,segmentTimeline:r.timeline,loaderType:e.loaderType_,audioDisabled:e.audioDisabled_})&&!!((r=e.timelineChangeController_)&&(t=r.pendingTimelineChange({type:"audio"}),r=r.pendingTimelineChange({type:"main"}),s=(i=t&&r)&&t.to!==r.to,i)&&-1!==t.from&&-1!==r.from&&s)&&(t=(i=e).timelineChangeController_.pendingTimelineChange({type:"audio"}),i=i.timelineChangeController_.pendingTimelineChange({type:"main"}),t&&i&&t.to!!e&&Math.round(e)>t+$d,tc=(e,t)=>{var i,s,r;return"hls"===t&&(t=(e=>{let s=0;return["video","audio"].forEach(function(t){t=e[t+"TimingInfo"];if(t){var{start:t,end:i}=t;let e;"bigint"==typeof t||"bigint"==typeof i?e=window.BigInt(i)-window.BigInt(t):"number"==typeof t&&"number"==typeof i&&(e=i-t),"undefined"!=typeof e&&e>s&&(s=e)}}),s="bigint"==typeof s&&s{var i,s,r;if(t)return i=Boolean(t.key||t.map&&t.map.ke),s=Boolean(t.map&&!t.map.bytes),r=void 0===t.startOfSegment?t.start:t.startOfSegment,{type:e||t.type,uri:t.resolvedUri||t.uri,start:r,duration:t.duration,isEncrypted:i,isMediaInitialization:s}};class sc extends E.EventTarget{constructor(e,t=0){if(super(),!e)throw new TypeError("Initialization settings are required");if("function"!=typeof e.currentTime)throw new TypeError("No currentTime getter specified");if(!e.mediaSource)throw new TypeError("No MediaSource specified");this.bandwidth=e.bandwidth,this.throughput={rate:0,count:0},this.roundTrip=NaN,this.resetStats_(),this.mediaIndex=null,this.partIndex=null,this.hasPlayed_=e.hasPlayed,this.currentTime_=e.currentTime,this.seekable_=e.seekable,this.seeking_=e.seeking,this.duration_=e.duration,this.mediaSource_=e.mediaSource,this.vhs_=e.vhs,this.loaderType_=e.loaderType,this.currentMediaInfo_=void 0,this.startingMediaInfo_=void 0,this.segmentMetadataTrack_=e.segmentMetadataTrack,this.goalBufferLength_=e.goalBufferLength,this.sourceType_=e.sourceType,this.sourceUpdater_=e.sourceUpdater,this.inbandTextTracks_=e.inbandTextTracks,this.state_="INIT",this.timelineChangeController_=e.timelineChangeController,this.shouldSaveSegmentTimingInfo_=!0,this.parse708captions_=e.parse708captions,this.useDtsForTimestampOffset_=e.useDtsForTimestampOffset,this.captionServices_=e.captionServices,this.exactManifestTimings=e.exactManifestTimings,this.addMetadataToTextTrack=e.addMetadataToTextTrack,this.checkBufferTimeout_=null,this.error_=void 0,this.currentTimeline_=-1,this.shouldForceTimestampOffsetAfterResync_=!1,this.pendingSegment_=null,this.xhrOptions_=null,this.pendingSegments_=[],this.audioDisabled_=!1,this.isPendingTimestampOffset_=!1,this.gopBuffer_=[],this.timeMapping_=0,this.safeAppend_=!1,this.appendInitSegment_={audio:!0,video:!0},this.playlistOfLastInitSegment_={audio:null,video:null},this.callQueue_=[],this.loadQueue_=[],this.metadataQueue_={id3:[],caption:[]},this.waitingOnRemove_=!1,this.quotaExceededErrorRetryTimeout_=null,this.activeInitSegmentId_=null,this.initSegments_={},this.cacheEncryptionKeys_=e.cacheEncryptionKeys,this.keyCache_={},this.decrypter_=e.decrypter,this.syncController_=e.syncController,this.syncPoint_={segmentIndex:0,time:0},this.transmuxer_=this.createTransmuxer_(),this.triggerSyncInfoUpdate_=()=>this.trigger("syncinfoupdate"),this.syncController_.on("syncinfoupdate",this.triggerSyncInfoUpdate_),this.mediaSource_.addEventListener("sourceopen",()=>{this.isEndOfStream_()||(this.ended_=!1)}),this.fetchAtBuffer_=!1,this.logger_=Bd(`SegmentLoader[${this.loaderType_}]`),Object.defineProperty(this,"state",{get(){return this.state_},set(e){e!==this.state_&&(this.logger_(this.state_+" -> "+e),this.state_=e,this.trigger("statechange"))}}),this.sourceUpdater_.on("ready",()=>{this.hasEnoughInfoToAppend_()?this.processCallQueue_():Zu(this)}),this.sourceUpdater_.on("codecschange",e=>{this.trigger(f({type:"codecschange"},e))}),"main"===this.loaderType_&&this.timelineChangeController_.on("pendingtimelinechange",()=>{this.hasEnoughInfoToAppend_()?this.processCallQueue_():Zu(this)}),"audio"===this.loaderType_&&this.timelineChangeController_.on("timelinechange",e=>{this.trigger(f({type:"timelinechange"},e)),this.hasEnoughInfoToLoad_()?this.processLoadQueue_():Zu(this),this.hasEnoughInfoToAppend_()?this.processCallQueue_():Zu(this)})}get mediaSequenceSync_(){return this.syncController_.getMediaSequenceSync(this.loaderType_)}createTransmuxer_(){return vu({remux:!1,alignGopsAtEnd:this.safeAppend_,keepOriginalTimestamps:!0,parse708captions:this.parse708captions_,captionServices:this.captionServices_})}resetStats_(){this.mediaBytesTransferred=0,this.mediaRequests=0,this.mediaRequestsAborted=0,this.mediaRequestsTimedout=0,this.mediaRequestsErrored=0,this.mediaTransferDuration=0,this.mediaSecondsLoaded=0,this.mediaAppends=0}dispose(){this.trigger("dispose"),this.state="DISPOSED",this.pause(),this.abort_(),this.transmuxer_&&this.transmuxer_.terminate(),this.resetStats_(),this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.syncController_&&this.triggerSyncInfoUpdate_&&this.syncController_.off("syncinfoupdate",this.triggerSyncInfoUpdate_),this.off()}setAudio(e){this.audioDisabled_=!e,e?this.appendInitSegment_.audio=!0:this.sourceUpdater_.removeAudio(0,this.duration_())}abort(){"WAITING"!==this.state?(this.pendingSegment_&&(this.pendingSegment_=null),this.timelineChangeController_.clearPendingTimelineChange(this.loaderType_)):(this.abort_(),this.state="READY",this.paused()||this.monitorBuffer_())}abort_(){this.pendingSegment_&&this.pendingSegment_.abortRequests&&this.pendingSegment_.abortRequests(),this.pendingSegment_=null,this.callQueue_=[],this.loadQueue_=[],this.metadataQueue_.id3=[],this.metadataQueue_.caption=[],this.timelineChangeController_.clearPendingTimelineChange(this.loaderType_),this.waitingOnRemove_=!1,window.clearTimeout(this.quotaExceededErrorRetryTimeout_),this.quotaExceededErrorRetryTimeout_=null}checkForAbort_(e){return"APPENDING"!==this.state||this.pendingSegment_?!this.pendingSegment_||this.pendingSegment_.requestId!==e:(this.state="READY",!0)}error(e){return"undefined"!=typeof e&&(this.logger_("error occurred:",e),this.error_=e),this.pendingSegment_=null,this.error_}endOfStream(){this.ended_=!0,this.transmuxer_&&_u(this.transmuxer_),this.gopBuffer_.length=0,this.pause(),this.trigger("ended")}buffered_(){var e=this.getMediaInfo_();if(!this.sourceUpdater_||!e)return O();if("main"===this.loaderType_){var{hasAudio:e,hasVideo:t,isMuxed:i}=e;if(t&&e&&!this.audioDisabled_&&!i)return this.sourceUpdater_.buffered();if(t)return this.sourceUpdater_.videoBuffered()}return this.sourceUpdater_.audioBuffered()}initSegmentForMap(e,t=!1){if(!e)return null;var i=jh(e);let s=this.initSegments_[i];return t&&!s&&e.bytes&&(this.initSegments_[i]=s={resolvedUri:e.resolvedUri,byterange:e.byterange,bytes:e.bytes,tracks:e.tracks,timescales:e.timescales}),s||e}segmentKey(e,t=!1){if(!e)return null;var i=Vh(e);let s=this.keyCache_[i];this.cacheEncryptionKeys_&&t&&!s&&e.bytes&&(this.keyCache_[i]=s={resolvedUri:e.resolvedUri,bytes:e.bytes});t={resolvedUri:(s||e).resolvedUri};return s&&(t.bytes=s.bytes),t}couldBeginLoading_(){return this.playlist_&&!this.paused()}load(){if(this.monitorBuffer_(),this.playlist_)return"INIT"===this.state&&this.couldBeginLoading_()?this.init_():void(!this.couldBeginLoading_()||"READY"!==this.state&&"INIT"!==this.state||(this.state="READY"))}init_(){return this.state="READY",this.resetEverything(),this.monitorBuffer_()}playlist(t,i={}){if(t&&!(this.playlist_&&this.playlist_.endList&&t.endList&&this.playlist_.uri===t.uri)){var s,r=this.playlist_,n=this.pendingSegment_;this.playlist_=t,this.xhrOptions_=i,"INIT"===this.state&&(t.syncInfo={mediaSequence:t.mediaSequence,time:0},"main"===this.loaderType_)&&this.syncController_.setDateTimeMappingForStart(t);let e=null;if(r&&(r.id?e=r.id:r.uri&&(e=r.uri)),this.logger_(`playlist update [${e} => ${t.id||t.uri}]`),this.mediaSequenceSync_&&(this.mediaSequenceSync_.update(t,this.currentTime_()),this.logger_(`Playlist update: +currentTime: ${this.currentTime_()} +bufferedEnd: ${jd(this.buffered_())} +`,this.mediaSequenceSync_.diagnostics)),this.trigger("syncinfoupdate"),"INIT"===this.state&&this.couldBeginLoading_())return this.init_();r&&r.uri===t.uri?(i=t.mediaSequence-r.mediaSequence,this.logger_(`live window shift [${i}]`),null!==this.mediaIndex&&(this.mediaIndex-=i,this.mediaIndex<0?(this.mediaIndex=null,this.partIndex=null):(s=this.playlist_.segments[this.mediaIndex],!this.partIndex||s.parts&&s.parts.length&&s.parts[this.partIndex]||(s=this.mediaIndex,this.logger_(`currently processing part (index ${this.partIndex}) no longer exists.`),this.resetLoader(),this.mediaIndex=s))),n&&(n.mediaIndex-=i,n.mediaIndex<0?(n.mediaIndex=null,n.partIndex=null):(0<=n.mediaIndex&&(n.segment=t.segments[n.mediaIndex]),0<=n.partIndex&&n.segment.parts&&(n.part=n.segment.parts[n.partIndex]))),this.syncController_.saveExpiredSegmentInfo(r,t)):(null!==this.mediaIndex&&(!t.endList&&"number"==typeof t.partTargetDuration?this.resetLoader():this.resyncLoader()),this.currentMediaInfo_=void 0,this.trigger("playlistupdate"))}}pause(){this.checkBufferTimeout_&&(window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=null)}paused(){return null===this.checkBufferTimeout_}resetEverything(e){this.ended_=!1,this.activeInitSegmentId_=null,this.appendInitSegment_={audio:!0,video:!0},this.resetLoader(),this.remove(0,1/0,e),this.transmuxer_&&(this.transmuxer_.postMessage({action:"clearAllMp4Captions"}),this.transmuxer_.postMessage({action:"reset"}))}resetLoader(){this.fetchAtBuffer_=!1,this.mediaSequenceSync_&&this.mediaSequenceSync_.resetAppendedStatus(),this.resyncLoader()}resyncLoader(){this.transmuxer_&&_u(this.transmuxer_),this.mediaIndex=null,this.partIndex=null,this.syncPoint_=null,this.isPendingTimestampOffset_=!1;var e=this.currentMediaInfo_&&this.currentMediaInfo_.isFmp4;"hls"!==this.sourceType_||e||(this.shouldForceTimestampOffsetAfterResync_=!0),this.callQueue_=[],this.loadQueue_=[],this.metadataQueue_.id3=[],this.metadataQueue_.caption=[],this.abort(),this.transmuxer_&&this.transmuxer_.postMessage({action:"clearParsedMp4Captions"})}remove(t,i,s=()=>{},r=!1){if((i=i===1/0?this.duration_():i)<=t)this.logger_("skipping remove because end ${end} is <= start ${start}");else if(this.sourceUpdater_&&this.getMediaInfo_()){let e=1;var n,a=()=>{0===--e&&s()};for(n in!r&&this.audioDisabled_||(e++,this.sourceUpdater_.removeAudio(t,i,a)),!r&&"main"!==this.loaderType_||(this.gopBuffer_=((t,i,e,s)=>{var r=Math.ceil((i-s)*Nd),n=Math.ceil((e-s)*Nd),i=t.slice();let a=t.length;for(;a--&&!(t[a].pts<=n););if(-1!==a){let e=a+1;for(;e--&&!(t[e].pts<=r););e=Math.max(e,0),i.splice(e,a-e+1)}return i})(this.gopBuffer_,t,i,this.timeMapping_),e++,this.sourceUpdater_.removeVideo(t,i,a)),this.inbandTextTracks_)zu(t,i,this.inbandTextTracks_[n]);zu(t,i,this.segmentMetadataTrack_),a()}else this.logger_("skipping remove because no source updater or starting media info")}monitorBuffer_(){this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=window.setTimeout(this.monitorBufferTick_.bind(this),1)}monitorBufferTick_(){"READY"===this.state&&this.fillBuffer_(),this.checkBufferTimeout_&&window.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=window.setTimeout(this.monitorBufferTick_.bind(this),500)}fillBuffer_(){var e,t;this.sourceUpdater_.updating()||(e=this.chooseNextRequest_())&&(t={segmentInfo:ic({type:this.loaderType_,segment:e})},this.trigger({type:"segmentselected",metadata:t}),"number"==typeof e.timestampOffset&&(this.isPendingTimestampOffset_=!1,this.timelineChangeController_.pendingTimelineChange({type:this.loaderType_,from:this.currentTimeline_,to:e.timeline})),this.loadSegment_(e))}isEndOfStream_(e=this.mediaIndex,t=this.playlist_,i=this.partIndex){var s;return!(!t||!this.mediaSource_)&&(s="number"==typeof e&&t.segments[e],e=e+1===t.segments.length,i=!s||!s.parts||i+1===s.parts.length,t.endList)&&"open"===this.mediaSource_.readyState&&e&&i}chooseNextRequest_(){var e=this.buffered_(),s=jd(e)||0,e=Vd(e,this.currentTime_()),r=!this.hasPlayed_()&&1<=e,n=e>=this.goalBufferLength_(),t=this.playlist_.segments;if(!t.length||r||n)return null;this.syncPoint_=this.syncPoint_||this.syncController_.getSyncPoint(this.playlist_,this.duration_(),this.currentTimeline_,this.currentTime_(),this.loaderType_);r={partIndex:null,mediaIndex:null,startOfSegment:null,playlist:this.playlist_,isSyncRequest:Boolean(!this.syncPoint_)};if(r.isSyncRequest)r.mediaIndex=function(t,i,s){i=i||[];var r=[];let n=0;for(let e=0;es))return e}return 0===r.length?0:r[r.length-1]}(this.currentTimeline_,t,s),this.logger_("choose next request. Can not find sync point. Fallback to media Index: "+r.mediaIndex);else if(null!==this.mediaIndex){var n=t[this.mediaIndex],a="number"==typeof this.partIndex?this.partIndex:-1;r.startOfSegment=n.end||s,n.parts&&n.parts[a+1]?(r.mediaIndex=this.mediaIndex,r.partIndex=a+1):r.mediaIndex=this.mediaIndex+1}else{let e,t,i;n=this.fetchAtBuffer_?s:this.currentTime_();if(this.mediaSequenceSync_&&this.logger_(`chooseNextRequest_ request after Quality Switch: +For TargetTime: ${n}. +CurrentTime: ${this.currentTime_()} +BufferedEnd: ${s} +Fetch At Buffer: ${this.fetchAtBuffer_} +`,this.mediaSequenceSync_.diagnostics),this.mediaSequenceSync_&&this.mediaSequenceSync_.isReliable){a=this.getSyncInfoFromMediaSequenceSync_(n);if(!a)return this.error({message:s="No sync info found while using media sequence sync",metadata:{errorType:E.Error.StreamingFailedToSelectNextSegment,error:new Error(s)}}),this.logger_("chooseNextRequest_ - no sync info found using media sequence sync"),null;this.logger_(`chooseNextRequest_ mediaSequence syncInfo (${a.start} --> ${a.end})`),e=a.segmentIndex,t=a.partIndex,i=a.start}else{this.logger_("chooseNextRequest_ - fallback to a regular segment selection algorithm, based on a syncPoint.");s=ph.getMediaInfoForTime({exactManifestTimings:this.exactManifestTimings,playlist:this.playlist_,currentTime:n,startingPartIndex:this.syncPoint_.partIndex,startingSegmentIndex:this.syncPoint_.segmentIndex,startTime:this.syncPoint_.time});e=s.segmentIndex,t=s.partIndex,i=s.startTime}r.getMediaInfoForTime=this.fetchAtBuffer_?"bufferedEnd "+n:"currentTime "+n,r.mediaIndex=e,r.startOfSegment=i,r.partIndex=t,this.logger_(`choose next request. Playlist switched and we have a sync point. Media Index: ${r.mediaIndex} `)}a=t[r.mediaIndex];let i=a&&"number"==typeof r.partIndex&&a.parts&&a.parts[r.partIndex];if(!a||"number"==typeof r.partIndex&&!i)return null;"number"!=typeof r.partIndex&&a.parts&&(r.partIndex=0,i=a.parts[0]);s=this.vhs_.playlists&&this.vhs_.playlists.main&&this.vhs_.playlists.main.independentSegments||this.playlist_.independentSegments,e||!i||s||i.independent||(0===r.partIndex?(e=(n=t[r.mediaIndex-1]).parts&&n.parts.length&&n.parts[n.parts.length-1])&&e.independent&&(--r.mediaIndex,r.partIndex=n.parts.length-1,r.independent="previous segment"):a.parts[r.partIndex-1].independent&&(--r.partIndex,r.independent="previous part")),s=this.mediaSource_&&"ended"===this.mediaSource_.readyState;return r.mediaIndex>=t.length-1&&s&&!this.seeking_()?null:(this.shouldForceTimestampOffsetAfterResync_&&(this.shouldForceTimestampOffsetAfterResync_=!1,r.forceTimestampOffset=!0,this.logger_("choose next request. Force timestamp offset after loader resync")),this.generateSegmentInfo_(r))}getSyncInfoFromMediaSequenceSync_(e){var t;return this.mediaSequenceSync_&&(e!==(t=Math.max(e,this.mediaSequenceSync_.start))&&this.logger_(`getSyncInfoFromMediaSequenceSync_. Pulled target time from ${e} to `+t),e=this.mediaSequenceSync_.getSyncInfoForTime(t))?e.isAppended?(t=this.mediaSequenceSync_.getSyncInfoForTime(e.end))?(t.isAppended&&this.logger_("getSyncInfoFromMediaSequenceSync_: We encounter unexpected scenario where next media sequence sync info is also appended!"),t):null:e:null}generateSegmentInfo_(e){var{independent:e,playlist:t,mediaIndex:i,startOfSegment:s,isSyncRequest:r,partIndex:n,forceTimestampOffset:a,getMediaInfoForTime:o}=e,l=t.segments[i],d="number"==typeof n&&l.parts[n],i={requestId:"segment-loader-"+Math.random(),uri:d&&d.resolvedUri||l.resolvedUri,mediaIndex:i,partIndex:d?n:null,isSyncRequest:r,startOfSegment:s,playlist:t,bytes:null,encryptedBytes:null,timestampOffset:null,timeline:l.timeline,duration:d&&d.duration||l.duration,segment:l,part:d,byteLength:0,transmuxer:this.transmuxer_,getMediaInfoForTime:o,independent:e},n="undefined"!=typeof a?a:this.isPendingTimestampOffset_,r=(i.timestampOffset=this.timestampOffsetForSegment_({segmentTimeline:l.timeline,currentTimeline:this.currentTimeline_,startOfSegment:s,buffered:this.buffered_(),overrideCheck:n}),jd(this.sourceUpdater_.audioBuffered()));return"number"==typeof r&&(i.audioAppendStart=r-this.sourceUpdater_.audioTimestampOffset()),this.sourceUpdater_.videoBuffered().length&&(i.gopsToAlignWith=((e,t,i)=>{if("undefined"==typeof t||null===t||!e.length)return[];var s=Math.ceil((t-i+3)*Nd);let r;for(r=0;rs);r++);return e.slice(r)})(this.gopBuffer_,this.currentTime_()-this.sourceUpdater_.videoTimestampOffset(),this.timeMapping_)),i}timestampOffsetForSegment_(e){return{segmentTimeline:e,currentTimeline:t,startOfSegment:i,buffered:s,overrideCheck:r}=[e][0],r||e!==t?!(e!ph.isIncompatible(e));let d=e.filter(ph.isEnabled);var e=(d=d.length?d:e.filter(e=>!ph.isDisabled(e))).filter(ph.hasAttribute.bind(null,"BANDWIDTH")).map(e=>{var t=l.getSyncPoint(e,r,o,i)?1:2;return{playlist:e,rebufferingImpact:ph.estimateSegmentRequestTime(n,s,e)*t-a}}),h=e.filter(e=>e.rebufferingImpact<=0);return qu(h,(e,t)=>Tu(t.playlist,e.playlist)),h.length?h[0]:(qu(e,(e,t)=>e.rebufferingImpact-t.rebufferingImpact),e[0]||null)}({main:this.vhs_.playlists.main,currentTime:e,bandwidth:i,duration:this.duration_(),segmentDuration:s,timeUntilRebuffer:r,currentTimeline:this.currentTimeline_,syncController:this.syncController_});if(n){var a=t-r-n.rebufferingImpact;let e=.5;r<=$d&&(e=1),!n.playlist||n.playlist.uri===this.playlist_.uri||a{a[e.stream]=a[e.stream]||{startTime:1/0,captions:[],endTime:0};var t=a[e.stream];t.startTime=Math.min(t.startTime,e.startTime+n),t.endTime=Math.max(t.endTime,e.endTime+n),t.captions.push(e)}),Object.keys(a).forEach(e=>{var{startTime:t,endTime:i,captions:s}=a[e],r=this.inbandTextTracks_;this.logger_(`adding cues from ${t} -> ${i} for `+e),function(r,n,a){if(!r[a]){n.trigger({type:"usage",name:"vhs-608"});let s=a;/^cc708_/.test(a)&&(s="SERVICE"+a.split("_")[1]);var o=n.textTracks().getTrackById(s);if(o)r[a]=o;else{let e=a,t=a,i=!1;o=(n.options_.vhs&&n.options_.vhs.captionServices||{})[s];o&&(e=o.label,t=o.language,i=o.default),r[a]=n.addRemoteTextTrack({kind:"captions",id:s,default:i,label:e,language:t},!1).track}}}(r,this.vhs_.tech_,e),zu(t,i,r[e]),function({inbandTextTracks:n,captionArray:e,timestampOffset:a}){if(e){let r=window.WebKitDataCue||window.VTTCue;e.forEach(i=>{let s=i.stream;i.content?i.content.forEach(e=>{var t=new r(i.startTime+a,i.endTime+a,e.text);t.line=e.line,t.align="left",t.position=e.position,t.positionAlign="line-left",n[s].addCue(t)}):n[s].addCue(new r(i.startTime+a,i.endTime+a,i.text))})}}({captionArray:s,inbandTextTracks:r,timestampOffset:n})}),this.transmuxer_&&this.transmuxer_.postMessage({action:"clearParsedMp4Captions"})}else this.metadataQueue_.caption.push(this.handleCaptions_.bind(this,e,t))}handleId3_(e,t,i){this.earlyAbortWhenNeeded_(e.stats),this.checkForAbort_(e.requestId)||(this.pendingSegment_.hasAppendedData_?this.addMetadataToTextTrack(i,t,this.duration_()):this.metadataQueue_.id3.push(this.handleId3_.bind(this,e,t,i)))}processMetadataQueue_(){this.metadataQueue_.id3.forEach(e=>e()),this.metadataQueue_.caption.forEach(e=>e()),this.metadataQueue_.id3=[],this.metadataQueue_.caption=[]}processCallQueue_(){var e=this.callQueue_;this.callQueue_=[],e.forEach(e=>e())}processLoadQueue_(){var e=this.loadQueue_;this.loadQueue_=[],e.forEach(e=>e())}hasEnoughInfoToLoad_(){var e;return"audio"!==this.loaderType_||!(!(e=this.pendingSegment_)||this.getCurrentMediaInfo_()&&Ju({timelineChangeController:this.timelineChangeController_,currentTimeline:this.currentTimeline_,segmentTimeline:e.timeline,loaderType:this.loaderType_,audioDisabled:this.audioDisabled_}))}getCurrentMediaInfo_(e=this.pendingSegment_){return e&&e.trackInfo||this.currentMediaInfo_}getMediaInfo_(e=this.pendingSegment_){return this.getCurrentMediaInfo_(e)||this.startingMediaInfo_}getPendingSegmentPlaylist(){return this.pendingSegment_?this.pendingSegment_.playlist:null}hasEnoughInfoToAppend_(){var e,t,i,s;return!!this.sourceUpdater_.ready()&&!(this.waitingOnRemove_||this.quotaExceededErrorRetryTimeout_||(e=this.pendingSegment_,t=this.getCurrentMediaInfo_(),!e)||!t||({hasAudio:t,hasVideo:i,isMuxed:s}=t,i&&!e.videoTimingInfo)||t&&!this.audioDisabled_&&!s&&!e.audioTimingInfo||Ju({timelineChangeController:this.timelineChangeController_,currentTimeline:this.currentTimeline_,segmentTimeline:e.timeline,loaderType:this.loaderType_,audioDisabled:this.audioDisabled_}))}handleData_(t,e){if(this.earlyAbortWhenNeeded_(t.stats),!this.checkForAbort_(t.requestId))if(this.callQueue_.length||!this.hasEnoughInfoToAppend_())Zu(this),this.callQueue_.push(this.handleData_.bind(this,t,e));else{var i=this.pendingSegment_;if(this.setTimeMapping_(i.timeline),this.updateMediaSecondsLoaded_(i.part||i.segment),"closed"!==this.mediaSource_.readyState){if(t.map&&(t.map=this.initSegmentForMap(t.map,!0),i.segment.map=t.map),t.key&&this.segmentKey(t.key,!0),i.isFmp4=t.isFmp4,i.timingInfo=i.timingInfo||{},i.isFmp4)this.trigger("fmp4"),i.timingInfo.start=i[Qu(e.type)].start;else{t=this.getCurrentMediaInfo_(),t="main"===this.loaderType_&&t&&t.hasVideo;let e;t&&(e=i.videoTimingInfo.start),i.timingInfo.start=this.trueSegmentStart_({currentStart:i.timingInfo.start,playlist:i.playlist,mediaIndex:i.mediaIndex,currentVideoTimestampOffset:this.sourceUpdater_.videoTimestampOffset(),useVideoTimingInfo:t,firstVideoFrameTimeForData:e,videoTimingInfo:i.videoTimingInfo,audioTimingInfo:i.audioTimingInfo})}if(this.updateAppendInitSegmentStatus(i,e.type),this.updateSourceBufferTimestampOffset_(i),i.isSyncRequest){this.updateTimingInfoEnd_(i),this.syncController_.saveSegmentTimingInfo({segmentInfo:i,shouldSaveTimelineMapping:"main"===this.loaderType_});t=this.chooseNextRequest_();if(t.mediaIndex!==i.mediaIndex||t.partIndex!==i.partIndex)return void this.logger_("sync segment was incorrect, not appending");this.logger_("sync segment was correct, appending")}i.hasAppendedData_=!0,this.processMetadataQueue_(),this.appendData_(i,e)}}}updateAppendInitSegmentStatus(e,t){"main"!==this.loaderType_||"number"!=typeof e.timestampOffset||e.changedTimestampOffset||(this.appendInitSegment_={audio:!0,video:!0}),this.playlistOfLastInitSegment_[t]!==e.playlist&&(this.appendInitSegment_[t]=!0)}getInitSegmentAndUpdateState_({type:e,initSegment:t,map:i,playlist:s}){if(i){var r=jh(i);if(this.activeInitSegmentId_===r)return null;t=this.initSegmentForMap(i,!0).bytes,this.activeInitSegmentId_=r}return t&&this.appendInitSegment_[e]?(this.playlistOfLastInitSegment_[e]=s,this.appendInitSegment_[e]=!1,this.activeInitSegmentId_=null,t):null}handleQuotaExceededError_({segmentInfo:e,type:t,bytes:i},s){var r=this.sourceUpdater_.audioBuffered(),n=this.sourceUpdater_.videoBuffered(),a=(1{this.logger_("On QUOTA_EXCEEDED_ERR, retrying append in 1s"),this.waitingOnRemove_=!1,this.quotaExceededErrorRetryTimeout_=window.setTimeout(()=>{this.logger_("On QUOTA_EXCEEDED_ERR, re-processing call queue"),this.quotaExceededErrorRetryTimeout_=null,this.processCallQueue_()},1e3)},!0))}handleAppendError_({segmentInfo:e,type:t,bytes:i},s){s&&(22===s.code?this.handleQuotaExceededError_({segmentInfo:e,type:t,bytes:i}):(this.logger_("Received non QUOTA_EXCEEDED_ERR on append",s),this.error({message:`${t} append of ${i.length}b failed for segment `+`#${e.mediaIndex} in playlist `+e.playlist.id,metadata:{errorType:E.Error.StreamingFailedToAppendSegment}}),this.trigger("appenderror")))}appendToSourceBuffer_({segmentInfo:e,type:t,initSegment:i,data:s,bytes:r}){if(!r){var n=[s];let e=s.byteLength;i&&(n.unshift(i),e+=i.byteLength),r=(e=>{let t=0,i;return e.bytes&&(i=new Uint8Array(e.bytes),e.segments.forEach(e=>{i.set(e,t),t+=e.byteLength})),i})({bytes:e,segments:n})}s={segmentInfo:ic({type:this.loaderType_,segment:e})};this.trigger({type:"segmentappendstart",metadata:s}),this.sourceUpdater_.appendBuffer({segmentInfo:e,type:t,bytes:r},this.handleAppendError_.bind(this,{segmentInfo:e,type:t,bytes:r}))}handleSegmentTimingInfo_(e,t,i){this.pendingSegment_&&t===this.pendingSegment_.requestId&&((t=this.pendingSegment_.segment)[e=e+"TimingInfo"]||(t[e]={}),t[e].transmuxerPrependedSeconds=i.prependedContentDuration||0,t[e].transmuxedPresentationStart=i.start.presentation,t[e].transmuxedDecodeStart=i.start.decode,t[e].transmuxedPresentationEnd=i.end.presentation,t[e].transmuxedDecodeEnd=i.end.decode,t[e].baseMediaDecodeTime=i.baseMediaDecodeTime)}appendData_(e,t){var{type:i,data:s}=t;s&&s.byteLength&&("audio"===i&&this.audioDisabled_||(t=this.getInitSegmentAndUpdateState_({type:i,initSegment:t.initSegment,playlist:e.playlist,map:e.isFmp4?e.segment.map:null}),this.appendToSourceBuffer_({segmentInfo:e,type:i,initSegment:t,data:s})))}loadSegment_(t){this.state="WAITING",this.pendingSegment_=t,this.trimBackBuffer_(t),"number"==typeof t.timestampOffset&&this.transmuxer_&&this.transmuxer_.postMessage({action:"clearAllMp4Captions"}),this.hasEnoughInfoToLoad_()?this.updateTransmuxerAndRequestSegment_(t):(Zu(this),this.loadQueue_.push(()=>{var e=f({},t,{forceTimestampOffset:!0});f(t,this.generateSegmentInfo_(e)),this.isPendingTimestampOffset_=!1,this.updateTransmuxerAndRequestSegment_(t)}))}updateTransmuxerAndRequestSegment_(s){this.shouldUpdateTransmuxerTimestampOffset_(s.timestampOffset)&&(this.gopBuffer_.length=0,s.gopsToAlignWith=[],this.timeMapping_=0,this.transmuxer_.postMessage({action:"reset"}),this.transmuxer_.postMessage({action:"setTimestampOffset",timestampOffset:s.timestampOffset}));var e=this.createSimplifiedSegmentObj_(s),t=this.isEndOfStream_(s.mediaIndex,s.playlist,s.partIndex),i=null!==this.mediaIndex,r=s.timeline!==this.currentTimeline_&&0{this.logger_("received endedtimeline callback")},id3Fn:this.handleId3_.bind(this),dataFn:this.handleData_.bind(this),doneFn:this.segmentRequestFinished_.bind(this),onTransmuxerLog:({message:e,level:t,stream:i})=>{this.logger_(Yu(s)+` logged from transmuxer stream ${i} as a ${t}: `+e)},triggerSegmentEventFn:({type:e,segment:t,keyInfo:i,trackInfo:s,timingInfo:r})=>{t={segmentInfo:ic({segment:t})};i&&(t.keyInfo=i),s&&(t.trackInfo=s),r&&(t.timingInfo=r),this.trigger({type:e,metadata:t})}})}trimBackBuffer_(e){var t=((e,t,i)=>{let s=t-R.BACK_BUFFER_LENGTH;return e.length&&(s=Math.max(s,e.start(0))),Math.min(t-i,s)})(this.seekable_(),this.currentTime_(),this.playlist_.targetDuration||10);0{if(!t.length)return e;if(i)return t.slice();var s=t[0].pts;let r=0;for(r;r=s);r++);return e.slice(0,r).concat(t)})(this.gopBuffer_,i.gopInfo,this.safeAppend_)),this.state="APPENDING",this.trigger("appending"),this.waitForAppendsToComplete_(e)}}setTimeMapping_(e){e=this.syncController_.mappingForTimeline(e);null!==e&&(this.timeMapping_=e)}updateMediaSecondsLoaded_(e){"number"==typeof e.start&&"number"==typeof e.end?this.mediaSecondsLoaded+=e.end-e.start:this.mediaSecondsLoaded+=e.duration}shouldUpdateTransmuxerTimestampOffset_(e){return null!==e&&("main"===this.loaderType_&&e!==this.sourceUpdater_.videoTimestampOffset()||!this.audioDisabled_&&e!==this.sourceUpdater_.audioTimestampOffset())}trueSegmentStart_({currentStart:e,playlist:t,mediaIndex:i,firstVideoFrameTimeForData:s,currentVideoTimestampOffset:r,useVideoTimingInfo:n,videoTimingInfo:a,audioTimingInfo:o}){return"undefined"!=typeof e?e:n?(e=t.segments[i-1],0!==i&&e&&"undefined"!=typeof e.start&&e.end===s+r?a.start:s):o.start}waitForAppendsToComplete_(e){var t,i,s=this.getCurrentMediaInfo_(e);s?({hasAudio:s,hasVideo:i,isMuxed:t}=s,i="main"===this.loaderType_&&i,s=!this.audioDisabled_&&s&&!t,e.waitingOnAppends=0,e.hasAppendedData_?(i&&e.waitingOnAppends++,s&&e.waitingOnAppends++,i&&this.sourceUpdater_.videoQueueCallback(this.checkAppendsDone_.bind(this,e)),s&&this.sourceUpdater_.audioQueueCallback(this.checkAppendsDone_.bind(this,e))):(e.timingInfo||"number"!=typeof e.timestampOffset||(this.isPendingTimestampOffset_=!0),e.timingInfo={start:0},e.waitingOnAppends++,this.isPendingTimestampOffset_||(this.updateSourceBufferTimestampOffset_(e),this.processMetadataQueue_()),this.checkAppendsDone_(e))):(this.error({message:"No starting media returned, likely due to an unsupported media format.",playlistExclusionDuration:1/0}),this.trigger("error"))}checkAppendsDone_(e){this.checkForAbort_(e.requestId)||(e.waitingOnAppends--,0===e.waitingOnAppends&&this.handleAppendsDone_())}checkForIllegalMediaSwitch(e){i=this.loaderType_,t=this.getCurrentMediaInfo_(),e=e;var t,i="main"===i&&t&&e?e.hasAudio||e.hasVideo?t.hasVideo&&!e.hasVideo?"Only audio found in segment when we expected video. We can't switch to audio only from a stream that had video. To get rid of this message, please add codec information to the manifest.":!t.hasVideo&&e.hasVideo?"Video found in segment when we expected only audio. We can't switch to a stream with video from an audio only stream. To get rid of this message, please add codec information to the manifest.":null:"Neither audio nor video found in segment.":null;return!!i&&(this.error({message:i,playlistExclusionDuration:1/0}),this.trigger("error"),!0)}updateSourceBufferTimestampOffset_(t){if(null!==t.timestampOffset&&"number"==typeof t.timingInfo.start&&!t.changedTimestampOffset&&"main"===this.loaderType_){let e=!1;t.timestampOffset-=this.getSegmentStartTimeForTimestampOffsetCalculation_({videoTimingInfo:t.segment.videoTimingInfo,audioTimingInfo:t.segment.audioTimingInfo,timingInfo:t.timingInfo}),t.changedTimestampOffset=!0,t.timestampOffset!==this.sourceUpdater_.videoTimestampOffset()&&(this.sourceUpdater_.videoTimestampOffset(t.timestampOffset),e=!0),t.timestampOffset!==this.sourceUpdater_.audioTimestampOffset()&&(this.sourceUpdater_.audioTimestampOffset(t.timestampOffset),e=!0),e&&this.trigger("timestampoffset")}}getSegmentStartTimeForTimestampOffsetCalculation_({videoTimingInfo:e,audioTimingInfo:t,timingInfo:i}){return this.useDtsForTimestampOffset_?e&&"number"==typeof e.transmuxedDecodeStart?e.transmuxedDecodeStart:t&&"number"==typeof t.transmuxedDecodeStart?t.transmuxedDecodeStart:i.start:i.start}updateTimingInfoEnd_(e){e.timingInfo=e.timingInfo||{};var t=this.getMediaInfo_(),t="main"===this.loaderType_&&t&&t.hasVideo&&e.videoTimingInfo?e.videoTimingInfo:e.audioTimingInfo;t&&(e.timingInfo.end="number"==typeof t.end?t.end:t.start+e.duration)}handleAppendsDone_(){var e,t,i;this.pendingSegment_&&(e={segmentInfo:ic({type:this.loaderType_,segment:this.pendingSegment_})},this.trigger({type:"appendsdone",metadata:e})),this.pendingSegment_?((e=this.pendingSegment_).part&&e.part.syncInfo?e.part.syncInfo.markAppended():e.segment.syncInfo&&e.segment.syncInfo.markAppended(),this.updateTimingInfoEnd_(e),this.shouldSaveSegmentTimingInfo_&&this.syncController_.saveSegmentTimingInfo({segmentInfo:e,shouldSaveTimelineMapping:"main"===this.loaderType_}),(t=tc(e,this.sourceType_))&&("warn"===t.severity?E.log.warn(t.message):this.logger_(t.message)),this.recordThroughput_(e),this.pendingSegment_=null,this.state="READY",e.isSyncRequest&&(this.trigger("syncinfoupdate"),!e.hasAppendedData_)?this.logger_("Throwing away un-appended sync request "+Yu(e)):(this.logger_("Appended "+Yu(e)),this.addSegmentMetadataCue_(e),this.fetchAtBuffer_=!0,this.currentTimeline_!==e.timeline&&(this.timelineChangeController_.lastTimelineChange({type:this.loaderType_,from:this.currentTimeline_,to:e.timeline}),"main"!==this.loaderType_||this.audioDisabled_||this.timelineChangeController_.lastTimelineChange({type:"audio",from:this.currentTimeline_,to:e.timeline})),this.currentTimeline_=e.timeline,this.trigger("syncinfoupdate"),t=e.segment,i=e.part,t=t.end&&this.currentTime_()-t.end>3*e.playlist.targetDuration,i=i&&i.end&&this.currentTime_()-i.end>3*e.playlist.partTargetDuration,t||i?(this.logger_(`bad ${t?"segment":"part"} `+Yu(e)),this.resetEverything()):(null!==this.mediaIndex&&this.trigger("bandwidthupdate"),this.trigger("progress"),this.mediaIndex=e.mediaIndex,this.partIndex=e.partIndex,this.isEndOfStream_(e.mediaIndex,e.playlist,e.partIndex)&&this.endOfStream(),this.trigger("appended"),e.hasAppendedData_&&this.mediaAppends++,this.paused()||this.monitorBuffer_()))):(this.state="READY",this.paused()||this.monitorBuffer_())}recordThroughput_(e){var t,i;e.duration<1/60?this.logger_("Ignoring segment's throughput because its duration of "+e.duration+" is less than the min to record "+1/60):(t=this.throughput.rate,i=Date.now()-e.endOfAllRequests+1,e=Math.floor(e.byteLength/i*8*1e3),this.throughput.rate+=(e-t)/++this.throughput.count)}addSegmentMetadataCue_(e){var t,i,s,r;this.segmentMetadataTrack_&&(t=(r=e.segment).start,i=r.end,Ku(t))&&Ku(i)&&(zu(t,i,this.segmentMetadataTrack_),s=window.WebKitDataCue||window.VTTCue,r={custom:r.custom,dateTimeObject:r.dateTimeObject,dateTimeString:r.dateTimeString,programDateTime:r.programDateTime,bandwidth:e.playlist.attributes.BANDWIDTH,resolution:e.playlist.attributes.RESOLUTION,codecs:e.playlist.attributes.CODECS,byteLength:e.byteLength,uri:e.uri,timeline:e.timeline,playlist:e.playlist.id,start:t,end:i},(e=new s(t,i,JSON.stringify(r))).value=r,this.segmentMetadataTrack_.addCue(e))}}function rc(){}function nc(e){return"string"!=typeof e?e:e.replace(/./,e=>e.toUpperCase())}let ac=["video","audio"],oc=(e,t)=>{var i=t[e+"Buffer"];return i&&i.updating||t.queuePending[e]},lc=(i,s)=>{if(0!==s.queue.length){let e=0,t=s.queue[e];if("mediaSource"===t.type)s.updating()||"closed"===s.mediaSource.readyState||(s.queue.shift(),t.action(s),t.doneFn&&t.doneFn(),lc("audio",s),lc("video",s));else if("mediaSource"!==i&&s.ready()&&"closed"!==s.mediaSource.readyState&&!oc(i,s)){if(t.type!==i){if(null===(e=((t,i)=>{for(let e=0;e{var i=t[e+"Buffer"],s=nc(e);i&&(i.removeEventListener("updateend",t[`on${s}UpdateEnd_`]),i.removeEventListener("error",t[`on${s}Error_`]),t.codecs[e]=null,t[e+"Buffer"]=null)},hc=(e,t)=>e&&t&&-1!==Array.prototype.indexOf.call(e.sourceBuffers,t),uc={appendBuffer:(s,r,n)=>(t,i)=>{var e=i[t+"Buffer"];if(hc(i.mediaSource,e)){i.logger_(`Appending segment ${r.mediaIndex}'s ${s.length} bytes to ${t}Buffer`);try{e.appendBuffer(s)}catch(e){i.logger_(`Error with code ${e.code} `+(22===e.code?"(QUOTA_EXCEEDED_ERR) ":"")+`when appending segment ${r.mediaIndex} to ${t}Buffer`),i.queuePending[t]=null,n(e)}}},remove:(s,r)=>(t,i)=>{var e=i[t+"Buffer"];if(hc(i.mediaSource,e)){i.logger_(`Removing ${s} to ${r} from ${t}Buffer`);try{e.remove(s,r)}catch(e){i.logger_(`Remove ${s} to ${r} from ${t}Buffer failed`)}}},timestampOffset:s=>(e,t)=>{var i=t[e+"Buffer"];hc(t.mediaSource,i)&&(t.logger_(`Setting ${e}timestampOffset to `+s),i.timestampOffset=s)},callback:i=>(e,t)=>{i()},endOfStream:t=>e=>{if("open"===e.mediaSource.readyState){e.logger_(`Calling mediaSource endOfStream(${t||""})`);try{e.mediaSource.endOfStream(t)}catch(e){E.log.warn("Failed to call media source endOfStream",e)}}},duration:t=>e=>{e.logger_("Setting mediaSource duration to "+t);try{e.mediaSource.duration=t}catch(e){E.log.warn("Failed to set media source duration",e)}},abort:()=>(t,e)=>{if("open"===e.mediaSource.readyState){var i=e[t+"Buffer"];if(hc(e.mediaSource,i)){e.logger_(`calling abort on ${t}Buffer`);try{i.abort()}catch(e){E.log.warn(`Failed to abort on ${t}Buffer`,e)}}}},addSourceBuffer:(s,r)=>e=>{var t=nc(s),i=oa(r),i=(e.logger_(`Adding ${s}Buffer with codec ${r} to mediaSource`),e.mediaSource.addSourceBuffer(i));i.addEventListener("updateend",e[`on${t}UpdateEnd_`]),i.addEventListener("error",e[`on${t}Error_`]),e.codecs[s]=r,e[s+"Buffer"]=i},removeSourceBuffer:i=>e=>{var t=e[i+"Buffer"];if(dc(i,e),hc(e.mediaSource,t)){e.logger_(`Removing ${i}Buffer with codec ${e.codecs[i]} from mediaSource`);try{e.mediaSource.removeSourceBuffer(t)}catch(e){E.log.warn(`Failed to removeSourceBuffer ${i}Buffer`,e)}}},changeType:o=>(t,i)=>{var e=i[t+"Buffer"],s=oa(o);if(hc(i.mediaSource,e)){var r=o.substring(0,o.indexOf(".")),n=i.codecs[t],a=n.substring(0,n.indexOf("."));if(a!==r){a={codecsChangeInfo:{from:n,to:o}};i.trigger({type:"codecschange",metadata:a}),i.logger_(`changing ${t}Buffer codec from ${n} to `+o);try{e.changeType(s),i.codecs[t]=o}catch(e){a.errorType=E.Error.StreamingCodecsChangeError,(a.error=e).metadata=a,i.error_=e,i.trigger("error"),E.log.warn(`Failed to changeType on ${t}Buffer`,e)}}}}},cc=({type:e,sourceUpdater:t,action:i,doneFn:s,name:r})=>{t.queue.push({type:e,action:i,doneFn:s,name:r}),lc(e,t)},pc=(i,s)=>e=>{var t=function(t){if(0===t.length)return"Buffered Ranges are empty";let i="Buffered Ranges: \n";for(let e=0;e ${r}. Duration (${r-s}) +`}return i}(s[i+"Buffered"]());s.logger_(`received "updateend" event for ${i} Source Buffer: `,t),s.queuePending[i]&&(t=s.queuePending[i].doneFn,s.queuePending[i]=null,t)&&t(s[i+"Error_"]),lc(i,s)};class mc extends E.EventTarget{constructor(e){super(),this.mediaSource=e,this.sourceopenListener_=()=>lc("mediaSource",this),this.mediaSource.addEventListener("sourceopen",this.sourceopenListener_),this.logger_=Bd("SourceUpdater"),this.audioTimestampOffset_=0,this.videoTimestampOffset_=0,this.queue=[],this.queuePending={audio:null,video:null},this.delayedAudioAppendQueue_=[],this.videoAppendQueued_=!1,this.codecs={},this.onVideoUpdateEnd_=pc("video",this),this.onAudioUpdateEnd_=pc("audio",this),this.onVideoError_=e=>{this.videoError_=e},this.onAudioError_=e=>{this.audioError_=e},this.createdSourceBuffers_=!1,this.initializedEme_=!1,this.triggeredReady_=!1}initializedEme(){this.initializedEme_=!0,this.triggerReady()}hasCreatedSourceBuffers(){return this.createdSourceBuffers_}hasInitializedAnyEme(){return this.initializedEme_}ready(){return this.hasCreatedSourceBuffers()&&this.hasInitializedAnyEme()}createSourceBuffers(e){this.hasCreatedSourceBuffers()||(this.addOrChangeSourceBuffers(e),this.createdSourceBuffers_=!0,this.trigger("createdsourcebuffers"),this.triggerReady())}triggerReady(){this.ready()&&!this.triggeredReady_&&(this.triggeredReady_=!0,this.trigger("ready"))}addSourceBuffer(e,t){cc({type:"mediaSource",sourceUpdater:this,action:uc.addSourceBuffer(e,t),name:"addSourceBuffer"})}abort(e){cc({type:e,sourceUpdater:this,action:uc.abort(e),name:"abort"})}removeSourceBuffer(e){this.canRemoveSourceBuffer()?cc({type:"mediaSource",sourceUpdater:this,action:uc.removeSourceBuffer(e),name:"removeSourceBuffer"}):E.log.error("removeSourceBuffer is not supported!")}canRemoveSourceBuffer(){return!E.browser.IS_FIREFOX&&window.MediaSource&&window.MediaSource.prototype&&"function"==typeof window.MediaSource.prototype.removeSourceBuffer}static canChangeType(){return window.SourceBuffer&&window.SourceBuffer.prototype&&"function"==typeof window.SourceBuffer.prototype.changeType}canChangeType(){return this.constructor.canChangeType()}changeType(e,t){this.canChangeType()?cc({type:e,sourceUpdater:this,action:uc.changeType(t),name:"changeType"}):E.log.error("changeType is not supported!")}addOrChangeSourceBuffers(i){if(!i||"object"!=typeof i||0===Object.keys(i).length)throw new Error("Cannot addOrChangeSourceBuffers to undefined codecs");Object.keys(i).forEach(e=>{var t=i[e];if(!this.hasCreatedSourceBuffers())return this.addSourceBuffer(e,t);this.canChangeType()&&this.changeType(e,t)})}appendBuffer(e,t){var{segmentInfo:i,type:s,bytes:r}=e;this.processedAppend_=!0,"audio"===s&&this.videoBuffer&&!this.videoAppendQueued_?(this.delayedAudioAppendQueue_.push([e,t]),this.logger_(`delayed audio append of ${r.length} until video append`)):(e=t,cc({type:s,sourceUpdater:this,action:uc.appendBuffer(r,i||{mediaIndex:-1},e),doneFn:t,name:"appendBuffer"}),"video"===s&&(this.videoAppendQueued_=!0,this.delayedAudioAppendQueue_.length)&&(r=this.delayedAudioAppendQueue_.slice(),this.logger_(`queuing delayed audio ${r.length} appendBuffers`),this.delayedAudioAppendQueue_.length=0,r.forEach(e=>{this.appendBuffer.apply(this,e)})))}audioBuffered(){return hc(this.mediaSource,this.audioBuffer)&&this.audioBuffer.buffered||O()}videoBuffered(){return hc(this.mediaSource,this.videoBuffer)&&this.videoBuffer.buffered||O()}buffered(){var e=hc(this.mediaSource,this.videoBuffer)?this.videoBuffer:null,t=hc(this.mediaSource,this.audioBuffer)?this.audioBuffer:null;return t&&!e?this.audioBuffered():e&&!t?this.videoBuffered():function(e,t){let i=null,s=null,r=0;var n=[],a=[];if(!(e&&e.length&&t&&t.length))return O();let o=e.length;for(;o--;)n.push({time:e.start(o),type:"start"}),n.push({time:e.end(o),type:"end"});for(o=t.length;o--;)n.push({time:t.start(o),type:"start"}),n.push({time:t.end(o),type:"end"});for(n.sort(function(e,t){return e.time-t.time}),o=0;o{this.abort(e),this.canRemoveSourceBuffer()?this.removeSourceBuffer(e):this[e+"QueueCallback"](()=>dc(e,this))}),this.videoAppendQueued_=!1,this.delayedAudioAppendQueue_.length=0,this.sourceopenListener_&&this.mediaSource.removeEventListener("sourceopen",this.sourceopenListener_),this.off()}}let gc=e=>decodeURIComponent(escape(String.fromCharCode.apply(null,e))),fc=new Uint8Array("\n\n".split("").map(e=>e.charCodeAt(0)));class yc extends Error{constructor(){super("Trying to parse received VTT cues, but there is no WebVTT. Make sure vtt.js is loaded.")}}class _c extends sc{constructor(e,t={}){super(e,t),this.mediaSource_=null,this.subtitlesTrack_=null,this.featuresNativeTextTracks_=e.featuresNativeTextTracks,this.loadVttJs=e.loadVttJs,this.shouldSaveSegmentTimingInfo_=!1}buffered_(){var e;return this.subtitlesTrack_&&this.subtitlesTrack_.cues&&this.subtitlesTrack_.cues.length?O([[(e=this.subtitlesTrack_.cues)[0].startTime,e[e.length-1].startTime]]):O()}initSegmentForMap(e,t=!1){if(!e)return null;var i=jh(e);let s=this.initSegments_[i];return t&&!s&&e.bytes&&(t=fc.byteLength+e.bytes.byteLength,(t=new Uint8Array(t)).set(e.bytes),t.set(fc,e.bytes.byteLength),this.initSegments_[i]=s={resolvedUri:e.resolvedUri,byterange:e.byterange,bytes:t}),s||e}couldBeginLoading_(){return this.playlist_&&this.subtitlesTrack_&&!this.paused()}init_(){return this.state="READY",this.resetEverything(),this.monitorBuffer_()}track(e){return"undefined"!=typeof e&&(this.subtitlesTrack_=e,"INIT"===this.state&&this.couldBeginLoading_())&&this.init_(),this.subtitlesTrack_}remove(e,t){zu(e,t,this.subtitlesTrack_)}fillBuffer_(){var e=this.chooseNextRequest_();e&&(null===this.syncController_.timestampOffsetForTimeline(e.timeline)?(this.syncController_.one("timestampoffset",()=>{this.state="READY",this.paused()||this.monitorBuffer_()}),this.state="WAITING_ON_TIMELINE"):this.loadSegment_(e))}timestampOffsetForSegment_(){return null}chooseNextRequest_(){return this.skipEmptySegments_(super.chooseNextRequest_())}skipEmptySegments_(e){for(;e&&e.segment.empty;){if(e.mediaIndex+1>=e.playlist.segments.length){e=null;break}e=this.generateSegmentInfo_({playlist:e.playlist,mediaIndex:e.mediaIndex+1,startOfSegment:e.startOfSegment+e.duration,isSyncRequest:e.isSyncRequest})}return e}stopForError(e){this.error(e),this.state="READY",this.pause(),this.trigger("error")}segmentRequestFinished_(e,t,i){if(this.subtitlesTrack_)if(this.saveTransferStats_(t.stats),this.pendingSegment_)if(e)e.code===wu.TIMEOUT&&this.handleTimeout_(),e.code===wu.ABORTED?this.mediaRequestsAborted+=1:this.mediaRequestsErrored+=1,this.stopForError(e);else{var s=this.pendingSegment_,r=i.mp4VttCues&&i.mp4VttCues.length,n=(r&&(s.mp4VttCues=i.mp4VttCues),this.saveBandwidthRelatedStats_(s.duration,t.stats),t.key&&this.segmentKey(t.key,!0),this.state="APPENDING",this.trigger("appending"),s.segment);if(n.map&&(n.map.bytes=t.map.bytes),s.bytes=t.bytes,"function"!=typeof window.WebVTT&&"function"==typeof this.loadVttJs)this.state="WAITING_ON_VTTJS",this.loadVttJs().then(()=>this.segmentRequestFinished_(e,t,i),()=>this.stopForError({message:"Error loading vtt.js"}));else{n.requested=!0;try{this.parseVTTCues_(s)}catch(e){return void this.stopForError({message:e.message,metadata:{errorType:E.Error.StreamingVttParserError,error:e}})}r||this.updateTimeMapping_(s,this.syncController_.timelines[s.timeline],this.playlist_),s.cues.length?s.timingInfo={start:s.cues[0].startTime,end:s.cues[s.cues.length-1].endTime}:s.timingInfo={start:s.startOfSegment,end:s.startOfSegment+s.duration},s.isSyncRequest?(this.trigger("syncinfoupdate"),this.pendingSegment_=null,this.state="READY"):(s.byteLength=s.bytes.byteLength,this.mediaSecondsLoaded+=n.duration,s.cues.forEach(e=>{this.subtitlesTrack_.addCue(this.featuresNativeTextTracks_?new window.VTTCue(e.startTime,e.endTime,e.text):e)}),function(t){var i=t.cues;if(i){var s={};for(let e=i.length-1;0<=e;e--){var r=i[e],n=r.startTime+`-${r.endTime}-`+r.text;s[n]?t.removeCue(r):s[n]=r}}}(this.subtitlesTrack_),this.handleAppendsDone_())}}else this.state="READY",this.mediaRequestsAborted+=1;else this.state="READY"}handleData_(e,t){var i=e&&"vtt"===e.type,s=t&&"text"===t.type;i&&s&&super.handleData_(e,t)}updateTimingInfoEnd_(){}parseMp4VttCues_(r){let n=null===this.sourceUpdater_.videoTimestampOffset()?this.sourceUpdater_.audioTimestampOffset():this.sourceUpdater_.videoTimestampOffset();r.mp4VttCues.forEach(e=>{var t=e.start+n,i=e.end+n;let s=new window.VTTCue(t,i,e.cueText);e.settings&&e.settings.split(" ").forEach(e=>{var e=e.split(":"),t=e[0],e=e[1];s[t]=isNaN(e)?e:Number(e)}),r.cues.push(s)})}parseVTTCues_(t){let i,s=!1;if("function"!=typeof window.WebVTT)throw new yc;if(t.cues=[],t.timestampmap={MPEGTS:0,LOCAL:0},t.mp4VttCues)this.parseMp4VttCues_(t);else{"function"==typeof window.TextDecoder?i=new window.TextDecoder("utf8"):(i=window.WebVTT.StringDecoder(),s=!0);var r=new window.WebVTT.Parser(window,window.vttjs,i);if(r.oncue=t.cues.push.bind(t.cues),r.ontimestampmap=e=>{t.timestampmap=e},r.onparsingerror=e=>{E.log.warn("Error encountered when parsing cues: "+e.message)},t.segment.map){let e=t.segment.map.bytes;s&&(e=gc(e)),r.parse(e)}let e=t.bytes;s&&(e=gc(e)),r.parse(e),r.flush()}}updateTimeMapping_(e,r,t){var i=e.segment;if(r)if(e.cues.length){var{MPEGTS:n,LOCAL:a}=e.timestampmap;let s=n/Nd-a+r.mapping;e.cues.forEach(e=>{var t=e.endTime-e.startTime,i=this.handleRollover_(e.startTime+s,r.time);e.startTime=Math.max(i,0),e.endTime=Math.max(i+t,0)}),t.syncInfo||(n=e.cues[0].startTime,a=e.cues[e.cues.length-1].startTime,t.syncInfo={mediaSequence:t.mediaSequence+e.mediaIndex,time:Math.min(n,a-i.duration)})}else i.empty=!0}handleRollover_(e,t){if(null===t)return e;let i=e*Nd;var s=t*Nd;let r;for(r=s=this.start&&ee.resetAppendedStatus())}}class Tc{constructor(){this.storage_=new Map,this.diagnostics_="",this.isReliable_=!1,this.start_=-1/0,this.end_=1/0}get start(){return this.start_}get end(){return this.end_}get diagnostics(){return this.diagnostics_}get isReliable(){return this.isReliable_}resetAppendedStatus(){this.storage_.forEach(e=>e.resetAppendStatus())}update(e,t){var{mediaSequence:e,segments:i}=e;if(this.isReliable_=this.isReliablePlaylist_(e,i),this.isReliable_)return this.updateStorage_(i,e,this.calculateBaseTime_(e,i,t))}getSyncInfoForTime(e){for(var{segmentSyncInfo:t,partsSyncInfo:i}of this.storage_.values())if(i.length){for(var s of i)if(s.isInRange(e))return s}else if(t.isInRange(e))return t;return null}getSyncInfoForMediaSequence(e){return this.storage_.get(e)}updateStorage_(e,t,i){let d=new Map,h="\n",u=i,c=t;this.start_=u,e.forEach((e,a)=>{let o=this.storage_.get(c);var t=u,i=t+e.duration,s=Boolean(o&&o.segmentSyncInfo&&o.segmentSyncInfo.isAppended),r=new vc({start:t,end:i,appended:s,segmentIndex:a});e.syncInfo=r;let l=u;var n=(e.parts||[]).map((e,t)=>{var i=l,s=l+e.duration,r=Boolean(o&&o.partsSyncInfo&&o.partsSyncInfo[t]&&o.partsSyncInfo[t].isAppended),n=new vc({start:i,end:s,appended:r,segmentIndex:a,partIndex:t});return l=s,h+=`Media Sequence: ${c}.${t} | Range: ${i} --> ${s} | Appended: ${r} +`,e.syncInfo=n});d.set(c,new bc(r,n)),h+=`${Hu(e.resolvedUri)} | Media Sequence: ${c} | Range: ${t} --> ${i} | Appended: ${s}\n`,c++,u=i}),this.end_=u,this.storage_=d,this.diagnostics_=h}calculateBaseTime_(e,i,t){if(!this.storage_.size)return 0;if(this.storage_.has(e))return this.storage_.get(e).segmentSyncInfo.start;var s=Math.min(...this.storage_.keys());if(e{return i!==1/0?{time:0,segmentIndex:0,partIndex:null}:null}},{name:"MediaSequence",run:(e,t,i,s,r,n)=>{e=e.getMediaSequenceSync(n);return e&&e.isReliable&&(n=e.getSyncInfoForTime(r))?{time:n.start,partIndex:n.partIndex,segmentIndex:n.segmentIndex}:null}},{name:"ProgramDateTime",run:(t,i,e,s,r)=>{if(!Object.keys(t.timelineToDatetimeMappings).length)return null;let n=null,a=null;var o=Qd(i);r=r||0;for(let e=0;e{let n=null,a=null;r=r||0;var o=Qd(t);for(let e=0;e=d)&&(a=d,n={time:h,segmentIndex:l.segmentIndex,partIndex:l.partIndex})}}return n}},{name:"Discontinuity",run:(i,s,e,t,r)=>{let n=null;if(r=r||0,s.discontinuityStarts&&s.discontinuityStarts.length){let t=null;for(let e=0;e=l)&&(t=l,n={time:o.time,segmentIndex:a,partIndex:null})}}}return n}},{name:"Playlist",run:(e,t,i,s,r)=>{return t.syncInfo?{time:t.syncInfo.time,segmentIndex:t.syncInfo.mediaSequence-t.mediaSequence,partIndex:null}:null}}];class Ec extends E.EventTarget{constructor(e=0){super(),this.timelines=[],this.discontinuities=[],this.timelineToDatetimeMappings={};var t=new Tc,i=new Sc(t),s=new Sc(t);this.mediaSequenceStorage_={main:t,audio:i,vtt:s},this.logger_=Bd("SyncController")}getMediaSequenceSync(e){return this.mediaSequenceStorage_[e]||null}getSyncPoint(e,t,i,s,r){if(t!==1/0)return wc.find(({name:e})=>"VOD"===e).run(this,e,t);var n,t=this.runStrategies_(e,t,i,s,r);if(!t.length)return null;for(n of t){var{syncPoint:a,strategy:o}=n,{segmentIndex:l,time:d}=a;if(!(l<0)){var h=d+e.segments[l].duration;if(this.logger_(`Strategy: ${o}. Current time: ${s}. selected segment: ${l}. Time: [${d} -> ${h}]}`),d<=s&&so){let e;e=a<0?s.start-Hd({defaultDuration:i.targetDuration,durationList:i.segments,startIndex:t.mediaIndex,endIndex:r}):s.end+Hd({defaultDuration:i.targetDuration,durationList:i.segments,startIndex:t.mediaIndex+1,endIndex:r}),this.discontinuities[n]={time:e,accuracy:o}}}}dispose(){this.trigger("dispose"),this.off()}}class Cc extends E.EventTarget{constructor(){super(),this.pendingTimelineChanges_={},this.lastTimelineChanges_={}}clearPendingTimelineChange(e){this.pendingTimelineChanges_[e]=null,this.trigger("pendingtimelinechange")}pendingTimelineChange({type:e,from:t,to:i}){return"number"==typeof t&&"number"==typeof i&&(this.pendingTimelineChanges_[e]={type:e,from:t,to:i},this.trigger("pendingtimelinechange")),this.pendingTimelineChanges_[e]}lastTimelineChange({type:e,from:t,to:i}){return"number"==typeof t&&"number"==typeof i&&(this.lastTimelineChanges_[e]={type:e,from:t,to:i},delete this.pendingTimelineChanges_[e],this.trigger({type:"timelinechange",metadata:{timelineChangeInfo:{from:t,to:i}}})),this.lastTimelineChanges_[e]}dispose(){this.trigger("dispose"),this.pendingTimelineChanges_={},this.lastTimelineChanges_={},this.off()}}var kc=au(ou(lu(function(){var e=function(){function e(){this.listeners={}}var t=e.prototype;return t.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)},t.off=function(e,t){return!!this.listeners[e]&&(t=this.listeners[e].indexOf(t),this.listeners[e]=this.listeners[e].slice(0),this.listeners[e].splice(t,1),-1>7))^n]=n;for(a=o=0;!s[a];a^=l||1,o=p[o]||1)for(u=(u=o^o<<1^o<<2^o<<3^o<<4)>>8^255&u^99,h=c[d=c[l=c[r[s[a]=u]=a]]],g=16843009*h^65537*d^257*l^16843008*a,m=257*c[u]^16843008*u,n=0;n<4;n++)t[n][a]=m=m<<24^m>>>8,i[n][u]=g=g<<24^g>>>8;for(n=0;n<5;n++)t[n]=t[n].slice(0),i[n]=i[n].slice(0);return e}(),this._tables=[[h[0][0].slice(),h[0][1].slice(),h[0][2].slice(),h[0][3].slice(),h[0][4].slice()],[h[1][0].slice(),h[1][1].slice(),h[1][2].slice(),h[1][3].slice(),h[1][4].slice()]];let t,i,s;var r=this._tables[0][4],n=this._tables[1],a=e.length;let o=1;if(4!==a&&6!==a&&8!==a)throw new Error("Invalid aes key size");var l=e.slice(0),d=[];for(this._key=[l,d],t=a;t<4*a+28;t++)s=l[t-1],(t%a==0||8===a&&t%a==4)&&(s=r[s>>>24]<<24^r[s>>16&255]<<16^r[s>>8&255]<<8^r[255&s],t%a==0)&&(s=s<<8^s>>>24^o<<24,o=o<<1^283*(o>>7)),l[t]=l[t-a]^s;for(i=0;t;i++,t--)s=l[3&i?t:t-4],t<=4||i<4?d[i]=s:d[i]=n[0][r[s>>>24]]^n[1][r[s>>16&255]]^n[2][r[s>>8&255]]^n[3][r[255&s]]}decrypt(e,t,i,s,r,n){var a,o,l=this._key[1];let d=e^l[0],h=s^l[1],u=i^l[2],c=t^l[3],p;var m=l.length/4-2;let g,f=4;var e=this._tables[1],y=e[0],_=e[1],v=e[2],b=e[3],T=e[4];for(g=0;g>>24]^_[h>>16&255]^v[u>>8&255]^b[255&c]^l[f],a=y[h>>>24]^_[u>>16&255]^v[c>>8&255]^b[255&d]^l[f+1],o=y[u>>>24]^_[c>>16&255]^v[d>>8&255]^b[255&h]^l[f+2],c=y[c>>>24]^_[d>>16&255]^v[h>>8&255]^b[255&u]^l[f+3],f+=4,d=p,h=a,u=o;for(g=0;g<4;g++)r[(3&-g)+n]=T[d>>>24]<<24^T[h>>16&255]<<16^T[u>>8&255]<<8^T[255&c]^l[f++],p=d,d=h,h=u,u=c,c=p}}class l extends e{constructor(){super(e),this.jobs=[],this.delay=1,this.timeout_=null}processJob_(){this.jobs.shift()(),this.jobs.length?this.timeout_=setTimeout(this.processJob_.bind(this),this.delay):this.timeout_=null}push(e){this.jobs.push(e),this.timeout_||(this.timeout_=setTimeout(this.processJob_.bind(this),this.delay))}}function f(e){return e<<24|(65280&e)<<8|(16711680&e)>>8|e>>>24}class d{constructor(e,t,i,s){var r=d.STEP,n=new Int32Array(e.buffer);let a=new Uint8Array(e.byteLength),o=0;for(this.asyncStream_=new l,this.asyncStream_.push(this.decryptChunk_(n.subarray(o,o+r),t,i,a)),o=r;o>2),l=new g(Array.prototype.slice.call(t)),t=new Uint8Array(e.byteLength),d=new Int32Array(t.buffer);let h,u,c,p,m;for(h=i[0],u=i[1],c=i[2],p=i[3],m=0;m{var t,i=s[e];t=i,("function"===ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer instanceof ArrayBuffer)?r[e]={bytes:i.buffer,byteOffset:i.byteOffset,byteLength:i.byteLength}:r[e]=i}),r}self.onmessage=function(e){let i=e.data;var e=new Uint8Array(i.encrypted.bytes,i.encrypted.byteOffset,i.encrypted.byteLength),t=new Uint32Array(i.key.bytes,i.key.byteOffset,i.key.byteLength/4),s=new Uint32Array(i.iv.bytes,i.iv.byteOffset,i.iv.byteLength/4);new d(e,t,s,function(e,t){self.postMessage(r({source:i.source,decrypted:t}),[t.buffer])})}})));let Ic=(e,t)=>{e.abort(),e.pause(),t&&t.activePlaylistLoader&&(t.activePlaylistLoader.pause(),t.activePlaylistLoader=null)},xc=(e,t)=>{(t.activePlaylistLoader=e).load()},Ac={AUDIO:(a,o)=>()=>{var{mediaTypes:{[a]:e},excludePlaylist:t}=o,i=e.activeTrack(),s=e.activeGroup(),s=(s.filter(e=>e.default)[0]||s[0]).id,r=e.tracks[s];if(i===r)t({error:{message:"Problem encountered loading the default audio track."}});else{for(var n in E.log.warn("Problem encountered loading the alternate audio track.Switching back to default."),e.tracks)e.tracks[n].enabled=e.tracks[n]===r;e.onTrackChanged()}},SUBTITLES:(i,s)=>()=>{var{[i]:e}=s.mediaTypes,t=(E.log.warn("Problem encountered loading the subtitle track.Disabling subtitle track."),e.activeTrack());t&&(t.mode="disabled"),e.onTrackChanged()}},Dc={AUDIO:(e,t,i)=>{if(!t)return;let{tech:s,requestOptions:r,segmentLoaders:{[e]:n}}=i;t.on("loadedmetadata",()=>{var e=t.media();n.playlist(e,r),(!s.paused()||e.endList&&"none"!==s.preload())&&n.load()}),t.on("loadedplaylist",()=>{n.playlist(t.media(),r),s.paused()||n.load()}),t.on("error",Ac[e](e,i))},SUBTITLES:(e,t,i)=>{let{tech:s,requestOptions:r,segmentLoaders:{[e]:n},mediaTypes:{[e]:a}}=i;t.on("loadedmetadata",()=>{var e=t.media();n.playlist(e,r),n.track(a.activeTrack()),(!s.paused()||e.endList&&"none"!==s.preload())&&n.load()}),t.on("loadedplaylist",()=>{n.playlist(t.media(),r),s.paused()||n.load()}),t.on("error",Ac[e](e,i))}},Pc={AUDIO:(i,s)=>{var r,n,{vhs:a,sourceType:o,segmentLoaders:{[i]:e},requestOptions:l,main:{mediaGroups:d},mediaTypes:{[i]:{groups:h,tracks:u,logger_:c}},mainPlaylistLoader:p}=s,m=ch(p.main);for(r in d[i]&&0!==Object.keys(d[i]).length||(d[i]={main:{default:{default:!0}}},m&&(d[i].main.default.playlists=p.main.playlists)),d[i])for(var g in h[r]||(h[r]=[]),d[i][r]){let e=d[i][r][g],t;t=m?(c(`AUDIO group '${r}' label '${g}' is a main playlist`),e.isMainPlaylist=!0,null):"vhs-json"===o&&e.playlists?new Nh(e.playlists[0],a,l):e.resolvedUri?new Nh(e.resolvedUri,a,l):e.playlists&&"dash"===o?new su(e.playlists[0],a,l,p):null,e=L({id:g,playlistLoader:t},e),Dc[i](i,e.playlistLoader,s),h[r].push(e),"undefined"==typeof u[g]&&(n=new E.AudioTrack({id:g,kind:(e=>{let t=e.default?"main":"alternative";return t=e.characteristics&&0<=e.characteristics.indexOf("public.accessibility.describes-video")?"main-desc":t})(e),enabled:!1,language:e.language,default:e.default,label:g}),u[g]=n)}e.on("error",Ac[i](i,s))},SUBTITLES:(i,s)=>{var r,n,{tech:a,vhs:o,sourceType:l,segmentLoaders:{[i]:e},requestOptions:d,main:{mediaGroups:h},mediaTypes:{[i]:{groups:u,tracks:c}},mainPlaylistLoader:p}=s;for(r in h[i])for(var m in u[r]||(u[r]=[]),h[i][r])if(o.options_.useForcedSubtitles||!h[i][r][m].forced){let e=h[i][r][m],t;if("hls"===l)t=new Nh(e.resolvedUri,o,d);else if("dash"===l){if(!e.playlists.filter(e=>e.excludeUntil!==1/0).length)return;t=new su(e.playlists[0],o,d,p)}else"vhs-json"===l&&(t=new Nh(e.playlists?e.playlists[0]:e.resolvedUri,o,d));e=L({id:m,playlistLoader:t},e),Dc[i](i,e.playlistLoader,s),u[r].push(e),"undefined"==typeof c[m]&&(n=a.addRemoteTextTrack({id:m,kind:"subtitles",default:e.default&&e.autoselect,language:e.language,label:m},!1).track,c[m]=n)}e.on("error",Ac[i](i,s))},"CLOSED-CAPTIONS":(e,t)=>{var i,{tech:s,main:{mediaGroups:r},mediaTypes:{[e]:{groups:n,tracks:a}}}=t;for(i in r[e])for(var o in n[i]||(n[i]=[]),r[e][i]){var l=r[e][i][o];if(/^(?:CC|SERVICE)/.test(l.instreamId)){var d=s.options_.vhs&&s.options_.vhs.captionServices||{};let e={label:o,language:l.language,instreamId:l.instreamId,default:l.default&&l.autoselect};void 0===(e=d[e.instreamId]?L(e,d[e.instreamId]):e).default&&delete e.default,n[i].push(L({id:o},l)),"undefined"==typeof a[o]&&(d=s.addRemoteTextTrack({id:e.instreamId,kind:"captions",default:e.default,language:e.language,label:e.label},!1).track,a[o]=d)}}}},Lc=(t,i)=>{for(let e=0;e()=>{var e,{[i]:{tracks:t}}=s.mediaTypes;for(e in t)if(t[e].enabled)return t[e];return null},SUBTITLES:(i,s)=>()=>{var e,{[i]:{tracks:t}}=s.mediaTypes;for(e in t)if("showing"===t[e].mode||"hidden"===t[e].mode)return t[e];return null}},Rc=n=>{["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(e=>{Pc[e](e,n)});let{mediaTypes:a,mainPlaylistLoader:e,tech:t,vhs:i,segmentLoaders:{AUDIO:s,main:r}}=n;["AUDIO","SUBTITLES"].forEach(e=>{var o,l,d,h,i,s,u,c,t,r;a[e].activeGroup=(o=e,l=n,t=>{var{mainPlaylistLoader:e,mediaTypes:{[o]:{groups:i}}}=l,s=e.media();if(!s)return null;let r=null;s.attributes[o]&&(r=i[s.attributes[o]]);var n=Object.keys(i);if(!r)if("AUDIO"===o&&1e.id===t.id)[0]||null}),a[e].activeTrack=Oc[e](e,n),a[e].onGroupChanged=(d=e,h=n,()=>{var{segmentLoaders:{[d]:e,main:t},mediaTypes:{[d]:i}}=h,s=i.activeTrack(),r=i.getActiveGroup(),n=i.activePlaylistLoader,a=i.lastGroup_;r&&a&&r.id===a.id||(i.lastGroup_=r,i.lastTrack_=s,Ic(e,i),r&&!r.isMainPlaylist&&(r.playlistLoader?(e.resyncLoader(),xc(r.playlistLoader,i)):n&&t.resetEverything()))}),a[e].onGroupChanging=(i=e,s=n,()=>{var{segmentLoaders:{[i]:e},mediaTypes:{[i]:t}}=s;t.lastGroup_=null,e.abort(),e.pause()}),a[e].onTrackChanged=(u=e,c=n,()=>{var e,t,{mainPlaylistLoader:i,segmentLoaders:{[u]:s,main:r},mediaTypes:{[u]:n}}=c,a=n.activeTrack(),o=n.getActiveGroup(),l=n.activePlaylistLoader,d=n.lastTrack_;if((!d||!a||d.id!==a.id)&&(n.lastGroup_=o,n.lastTrack_=a,Ic(s,n),o)){if(o.isMainPlaylist)return!a||!d||a.id===d.id||(t=(e=c.vhs.playlistController_).selectPlaylist(),e.media()===t)?void 0:(n.logger_(`track change. Switching main audio from ${d.id} to `+a.id),i.pause(),r.resetEverything(),void e.fastQualityChange_(t));if("AUDIO"===u){if(!o.playlistLoader)return r.setAudio(!0),void r.resetEverything();s.setAudio(!0),r.setAudio(!1)}l===o.playlistLoader||(s.track&&s.track(a),s.resetEverything()),xc(o.playlistLoader,n)}}),a[e].getActiveGroup=([t,r]=[e,n.mediaTypes],()=>{var e=r[t].activeTrack();return e?r[t].activeGroup(e):null})});var o,l=a.AUDIO.activeGroup();l&&(l=(l.filter(e=>e.default)[0]||l[0]).id,a.AUDIO.tracks[l].enabled=!0,a.AUDIO.onGroupChanged(),a.AUDIO.onTrackChanged(),(a.AUDIO.getActiveGroup().playlistLoader?(r.setAudio(!1),s):r).setAudio(!0)),e.on("mediachange",()=>{["AUDIO","SUBTITLES"].forEach(e=>a[e].onGroupChanged())}),e.on("mediachanging",()=>{["AUDIO","SUBTITLES"].forEach(e=>a[e].onGroupChanging())});let d=()=>{a.AUDIO.onTrackChanged(),t.trigger({type:"usage",name:"vhs-audio-change"})};for(o in t.audioTracks().addEventListener("change",d),t.remoteTextTracks().addEventListener("change",a.SUBTITLES.onTrackChanged),i.on("dispose",()=>{t.audioTracks().removeEventListener("change",d),t.remoteTextTracks().removeEventListener("change",a.SUBTITLES.onTrackChanged)}),t.clearTracks("audio"),a.AUDIO.tracks)t.audioTracks().addTrack(a.AUDIO.tracks[o])};class Nc{constructor(){this.priority_=[],this.pathwayClones_=new Map}set version(e){1===e&&(this.version_=e)}set ttl(e){this.ttl_=e||300}set reloadUri(e){e&&(this.reloadUri_=Md(this.reloadUri_,e))}set priority(e){e&&e.length&&(this.priority_=e)}set pathwayClones(e){e&&e.length&&(this.pathwayClones_=new Map(e.map(e=>[e.ID,e])))}get version(){return this.version_}get ttl(){return this.ttl_}get reloadUri(){return this.reloadUri_}get priority(){return this.priority_}get pathwayClones(){return this.pathwayClones_}}class Mc extends E.EventTarget{constructor(e,t){super(),this.currentPathway=null,this.defaultPathway=null,this.queryBeforeStart=!1,this.availablePathways_=new Set,this.steeringManifest=new Nc,this.proxyServerUrl_=null,this.manifestType_=null,this.ttlTimeout_=null,this.request_=null,this.currentPathwayClones=new Map,this.nextPathwayClones=new Map,this.excludedSteeringManifestURLs=new Set,this.logger_=Bd("Content Steering"),this.xhr_=e,this.getBandwidth_=t}assignTagProperties(e,t){this.manifestType_=t.serverUri?"HLS":"DASH";var i=t.serverUri||t.serverURL;i?i.startsWith("data:")?this.decodeDataUriManifest_(i.substring(i.indexOf(",")+1)):(this.steeringManifest.reloadUri=Md(e,i),this.defaultPathway=t.pathwayId||t.defaultServiceLocation,this.queryBeforeStart=t.queryBeforeStart,this.proxyServerUrl_=t.proxyServerURL,this.defaultPathway&&!this.queryBeforeStart&&this.trigger("content-steering")):(this.logger_(`steering manifest URL is ${i}, cannot request steering manifest.`),this.trigger("error"))}requestSteeringManifest(e){var t=this.steeringManifest.reloadUri;if(t){let r=e?t:this.getRequestURI(t);if(r){let s={contentSteeringInfo:{uri:r}};this.trigger({type:"contentsteeringloadstart",metadata:s}),this.request_=this.xhr_({uri:r,requestType:"content-steering-manifest"},(e,t)=>{if(e)return 410===t.status?(this.logger_(`manifest request 410 ${e}.`),this.logger_(`There will be no more content steering requests to ${r} this session.`),void this.excludedSteeringManifestURLs.add(r)):429===t.status?(t=t.responseHeaders["retry-after"],this.logger_(`manifest request 429 ${e}.`),this.logger_(`content steering will retry in ${t} seconds.`),void this.startTTLTimeout_(parseInt(t,10))):(this.logger_(`manifest failed to load ${e}.`),void this.startTTLTimeout_());this.trigger({type:"contentsteeringloadcomplete",metadata:s});let i;try{i=JSON.parse(this.request_.responseText)}catch(e){t={errorType:E.Error.StreamingContentSteeringParserError,error:e};this.trigger({type:"error",metadata:t})}this.assignSteeringProperties_(i);e={contentSteeringInfo:s.contentSteeringInfo,contentSteeringManifest:{version:this.steeringManifest.version,reloadUri:this.steeringManifest.reloadUri,priority:this.steeringManifest.priority}};this.trigger({type:"contentsteeringparsed",metadata:e}),this.startTTLTimeout_()})}else this.logger_("No valid content steering manifest URIs. Stopping content steering."),this.trigger("error"),this.dispose()}}setProxyServerUrl_(e){var e=new window.URL(e),t=new window.URL(this.proxyServerUrl_);return t.searchParams.set("url",encodeURI(e.toString())),this.setSteeringParams_(t.toString())}decodeDataUriManifest_(e){e=JSON.parse(window.atob(e));this.assignSteeringProperties_(e)}setSteeringParams_(e){var t,e=new window.URL(e),i=this.getPathway(),s=this.getBandwidth_();return i&&(t=`_${this.manifestType_}_pathway`,e.searchParams.set(t,i)),s&&(t=`_${this.manifestType_}_throughput`,e.searchParams.set(t,s)),e.toString()}assignSteeringProperties_(e){var t;this.steeringManifest.version=e.VERSION,this.steeringManifest.version?(this.steeringManifest.ttl=e.TTL,this.steeringManifest.reloadUri=e["RELOAD-URI"],this.steeringManifest.priority=e["PATHWAY-PRIORITY"]||e["SERVICE-LOCATION-PRIORITY"],this.steeringManifest.pathwayClones=e["PATHWAY-CLONES"],this.nextPathwayClones=this.steeringManifest.pathwayClones,this.availablePathways_.size||(this.logger_("There are no available pathways for content steering. Ending content steering."),this.trigger("error"),this.dispose()),t=(e=>{for(var t of e)if(this.availablePathways_.has(t))return t;return[...this.availablePathways_][0]})(this.steeringManifest.priority),this.currentPathway!==t&&(this.currentPathway=t,this.trigger("content-steering"))):(this.logger_(`manifest version is ${e.VERSION}, which is not supported.`),this.trigger("error"))}getPathway(){return this.currentPathway||this.defaultPathway}getRequestURI(e){if(!e)return null;var t=e=>this.excludedSteeringManifestURLs.has(e);if(this.proxyServerUrl_){var i=this.setProxyServerUrl_(e);if(!t(i))return i}i=this.setSteeringParams_(e);return t(i)?null:i}startTTLTimeout_(e=this.steeringManifest.ttl){this.ttlTimeout_=window.setTimeout(()=>{this.requestSteeringManifest()},1e3*e)}clearTTLTimeout_(){window.clearTimeout(this.ttlTimeout_),this.ttlTimeout_=null}abort(){this.request_&&this.request_.abort(),this.request_=null}dispose(){this.off("content-steering"),this.off("error"),this.abort(),this.clearTTLTimeout_(),this.currentPathway=null,this.defaultPathway=null,this.queryBeforeStart=null,this.proxyServerUrl_=null,this.manifestType_=null,this.ttlTimeout_=null,this.request_=null,this.excludedSteeringManifestURLs=new Set,this.availablePathways_=new Set,this.steeringManifest=new Nc}addAvailablePathway(e){e&&this.availablePathways_.add(e)}clearAvailablePathways(){this.availablePathways_.clear()}excludePathway(e){return this.availablePathways_.delete(e)}didDASHTagChange(e,t){return!t&&this.steeringManifest.reloadUri||t&&(Md(e,t.serverURL)!==this.steeringManifest.reloadUri||t.defaultServiceLocation!==this.defaultPathway||t.queryBeforeStart!==this.queryBeforeStart||t.proxyServerURL!==this.proxyServerUrl_)}getAvailablePathways(){return this.availablePathways_}}let Uc,Bc=["mediaRequests","mediaRequestsAborted","mediaRequestsTimedout","mediaRequestsErrored","mediaTransferDuration","mediaBytesTransferred","mediaAppends"];class Fc extends E.EventTarget{constructor(e){super(),this.fastQualityChange_=((t,i)=>{let s=null;return(...e)=>{clearTimeout(s),s=setTimeout(()=>{t.apply(null,e)},i)}})(this.fastQualityChange_.bind(this),100);let{src:t,withCredentials:i,tech:r,bandwidth:s,externVhs:n,useCueTags:a,playlistExclusionDuration:o,enableLowInitialPlaylist:l,sourceType:d,cacheEncryptionKeys:h,bufferBasedABR:u,leastPixelDiffSelector:c,captionServices:p,experimentalUseMMS:m}=e;if(!t)throw new Error("A non-empty playlist URL or JSON manifest string is required");let g=e.maxPlaylistRetries;null!==g&&"undefined"!=typeof g||(g=1/0),Uc=n,this.bufferBasedABR=Boolean(u),this.leastPixelDiffSelector=Boolean(c),this.withCredentials=i,this.tech_=r,this.vhs_=r.vhs,this.player_=e.player_,this.sourceType_=d,this.useCueTags_=a,this.playlistExclusionDuration=o,this.maxPlaylistRetries=g,this.enableLowInitialPlaylist=l,this.usingManagedMediaSource_=!1,this.useCueTags_&&(this.cueTagsTrack_=this.tech_.addTextTrack("metadata","ad-cues"),this.cueTagsTrack_.inBandMetadataTrackDispatchType=""),this.requestOptions_={withCredentials:i,maxPlaylistRetries:g,timeout:null},this.on("error",this.pauseLoading),this.mediaTypes_=(()=>{let t={};return["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(e=>{t[e]={groups:{},tracks:{},activePlaylistLoader:null,activeGroup:rc,activeTrack:rc,getActiveGroup:rc,onGroupChanged:rc,onTrackChanged:rc,lastTrack_:null,logger_:Bd(`MediaGroups[${e}]`)}}),t})(),m&&window.ManagedMediaSource?(this.tech_.el_.disableRemotePlayback=!0,this.mediaSource=new window.ManagedMediaSource,this.usingManagedMediaSource_=!0,E.log("Using ManagedMediaSource")):window.MediaSource&&(this.mediaSource=new window.MediaSource),this.handleDurationChange_=this.handleDurationChange_.bind(this),this.handleSourceOpen_=this.handleSourceOpen_.bind(this),this.handleSourceEnded_=this.handleSourceEnded_.bind(this),this.load=this.load.bind(this),this.pause=this.pause.bind(this),this.mediaSource.addEventListener("durationchange",this.handleDurationChange_),this.mediaSource.addEventListener("sourceopen",this.handleSourceOpen_),this.mediaSource.addEventListener("sourceended",this.handleSourceEnded_),this.mediaSource.addEventListener("startstreaming",this.load),this.mediaSource.addEventListener("endstreaming",this.pause),this.seekable_=O(),this.hasPlayed_=!1,this.syncController_=new Ec(e),this.segmentMetadataTrack_=r.addRemoteTextTrack({kind:"metadata",label:"segment-metadata"},!1).track,this.segmentMetadataTrack_.mode="hidden",this.decrypter_=new kc,this.sourceUpdater_=new mc(this.mediaSource),this.inbandTextTracks_={},this.timelineChangeController_=new Cc,this.keyStatusMap_=new Map;var f={vhs:this.vhs_,parse708captions:e.parse708captions,useDtsForTimestampOffset:e.useDtsForTimestampOffset,captionServices:p,mediaSource:this.mediaSource,currentTime:this.tech_.currentTime.bind(this.tech_),seekable:()=>this.seekable(),seeking:()=>this.tech_.seeking(),duration:()=>this.duration(),hasPlayed:()=>this.hasPlayed_,goalBufferLength:()=>this.goalBufferLength(),bandwidth:s,syncController:this.syncController_,decrypter:this.decrypter_,sourceType:this.sourceType_,inbandTextTracks:this.inbandTextTracks_,cacheEncryptionKeys:h,sourceUpdater:this.sourceUpdater_,timelineChangeController:this.timelineChangeController_,exactManifestTimings:e.exactManifestTimings,addMetadataToTextTrack:this.addMetadataToTextTrack.bind(this)},f=(this.mainPlaylistLoader_="dash"===this.sourceType_?new su(t,this.vhs_,L(this.requestOptions_,{addMetadataToTextTrack:this.addMetadataToTextTrack.bind(this)})):new Nh(t,this.vhs_,L(this.requestOptions_,{addDateRangesToTextTrack:this.addDateRangesToTextTrack_.bind(this)})),this.setupMainPlaylistLoaderListeners_(),this.mainSegmentLoader_=new sc(L(f,{segmentMetadataTrack:this.segmentMetadataTrack_,loaderType:"main"}),e),this.audioSegmentLoader_=new sc(L(f,{loaderType:"audio"}),e),this.subtitleSegmentLoader_=new _c(L(f,{loaderType:"vtt",featuresNativeTextTracks:this.tech_.featuresNativeTextTracks,loadVttJs:()=>new Promise((e,t)=>{function i(){r.off("vttjserror",s),e()}function s(){r.off("vttjsloaded",i),t()}r.one("vttjsloaded",i),r.one("vttjserror",s),r.addWebVttScript_()})}),e),this.contentSteeringController_=new Mc(this.vhs_.xhr,()=>this.mainSegmentLoader_.bandwidth),this.setupSegmentLoaderListeners_(),this.bufferBasedABR&&(this.mainPlaylistLoader_.one("loadedplaylist",()=>this.startABRTimer_()),this.tech_.on("pause",()=>this.stopABRTimer_()),this.tech_.on("play",()=>this.startABRTimer_())),Bc.forEach(e=>{this[e+"_"]=function(e){return this.audioSegmentLoader_[e]+this.mainSegmentLoader_[e]}.bind(this,e)}),this.logger_=Bd("pc"),this.triggeredFmp4Usage=!1,"none"===this.tech_.preload()?(this.loadOnPlay_=()=>{this.loadOnPlay_=null,this.mainPlaylistLoader_.load()},this.tech_.one("play",this.loadOnPlay_)):this.mainPlaylistLoader_.load(),this.timeToLoadedData__=-1,this.mainAppendsToLoadedData__=-1,this.audioAppendsToLoadedData__=-1,"none"===this.tech_.preload()?"play":"loadstart");this.tech_.one(f,()=>{let e=Date.now();this.tech_.one("loadeddata",()=>{this.timeToLoadedData__=Date.now()-e,this.mainAppendsToLoadedData__=this.mainSegmentLoader_.mediaAppends,this.audioAppendsToLoadedData__=this.audioSegmentLoader_.mediaAppends})})}mainAppendsToLoadedData_(){return this.mainAppendsToLoadedData__}audioAppendsToLoadedData_(){return this.audioAppendsToLoadedData__}appendsToLoadedData_(){var e=this.mainAppendsToLoadedData_(),t=this.audioAppendsToLoadedData_();return-1===e||-1===t?-1:e+t}timeToLoadedData_(){return this.timeToLoadedData__}checkABR_(e="abr"){var t=this.selectPlaylist();t&&this.shouldSwitchToMedia_(t)&&this.switchMedia_(t,e)}switchMedia_(e,t,i){var s=this.media(),s=s&&(s.id||s.uri),r=e&&(e.id||e.uri);s&&s!==r&&(this.logger_(`switch media ${s} -> ${r} from `+t),s={renditionInfo:{id:r,bandwidth:e.attributes.BANDWIDTH,resolution:e.attributes.RESOLUTION,codecs:e.attributes.CODECS},cause:t},this.trigger({type:"renditionselected",metadata:s}),this.tech_.trigger({type:"usage",name:"vhs-rendition-change-"+t})),this.mainPlaylistLoader_.media(e,i)}switchMediaForDASHContentSteering_(){["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(e=>{var t=this.mediaTypes_[e],t=t?t.activeGroup():null;let i=this.contentSteeringController_.getPathway();t&&i&&(t=(t.length?t[0]:t).playlists.filter(e=>e.attributes.serviceLocation===i)).length&&this.mediaTypes_[e].activePlaylistLoader.media(t[0])})}startABRTimer_(){this.stopABRTimer_(),this.abrTimer_=window.setInterval(()=>this.checkABR_(),250)}stopABRTimer_(){this.tech_.scrubbing&&this.tech_.scrubbing()||(window.clearInterval(this.abrTimer_),this.abrTimer_=null)}getAudioTrackPlaylists_(){var t=this.main(),e=t&&t.playlists||[];if(!t||!t.mediaGroups||!t.mediaGroups.AUDIO)return e;var i=t.mediaGroups.AUDIO,s=Object.keys(i);let r;if(Object.keys(this.mediaTypes_.AUDIO.groups).length)r=this.mediaTypes_.AUDIO.activeTrack();else{var n,a=i.main||s.length&&i[s[0]];for(n in a)if(a[n].default){r={label:n};break}}if(!r)return e;var o,l=[];for(o in i)if(i[o][r.label]){var d=i[o][r.label];if(d.playlists&&d.playlists.length)l.push.apply(l,d.playlists);else if(d.uri)l.push(d);else if(t.playlists.length)for(let e=0;e{var e=this.mainPlaylistLoader_.media(),t=1.5*e.targetDuration*1e3;hh(this.mainPlaylistLoader_.main,this.mainPlaylistLoader_.media())?this.requestOptions_.timeout=0:this.requestOptions_.timeout=t,e.endList&&"none"!==this.tech_.preload()&&(this.mainSegmentLoader_.playlist(e,this.requestOptions_),this.mainSegmentLoader_.load()),Rc({sourceType:this.sourceType_,segmentLoaders:{AUDIO:this.audioSegmentLoader_,SUBTITLES:this.subtitleSegmentLoader_,main:this.mainSegmentLoader_},tech:this.tech_,requestOptions:this.requestOptions_,mainPlaylistLoader:this.mainPlaylistLoader_,vhs:this.vhs_,main:this.main(),mediaTypes:this.mediaTypes_,excludePlaylist:this.excludePlaylist.bind(this)}),this.triggerPresenceUsage_(this.main(),e),this.setupFirstPlay(),!this.mediaTypes_.AUDIO.activePlaylistLoader||this.mediaTypes_.AUDIO.activePlaylistLoader.media()?this.trigger("selectedinitialmedia"):this.mediaTypes_.AUDIO.activePlaylistLoader.one("loadedmetadata",()=>{this.trigger("selectedinitialmedia")})}),this.mainPlaylistLoader_.on("loadedplaylist",()=>{this.loadOnPlay_&&this.tech_.off("play",this.loadOnPlay_);let t=this.mainPlaylistLoader_.media();if(!t){this.attachContentSteeringListeners_(),this.initContentSteeringController_(),this.excludeUnsupportedVariants_();let e;if(!(e=(e=this.enableLowInitialPlaylist?this.selectInitialPlaylist():e)||this.selectPlaylist())||!this.shouldSwitchToMedia_(e))return;if(this.initialMedia_=e,this.switchMedia_(this.initialMedia_,"initial"),!("vhs-json"===this.sourceType_&&this.initialMedia_.segments))return;t=this.initialMedia_}this.handleUpdatedMediaPlaylist(t)}),this.mainPlaylistLoader_.on("error",()=>{var e=this.mainPlaylistLoader_.error;this.excludePlaylist({playlistToExclude:e.playlist,error:e})}),this.mainPlaylistLoader_.on("mediachanging",()=>{this.mainSegmentLoader_.abort(),this.mainSegmentLoader_.pause()}),this.mainPlaylistLoader_.on("mediachange",()=>{var e=this.mainPlaylistLoader_.media(),t=1.5*e.targetDuration*1e3;hh(this.mainPlaylistLoader_.main,this.mainPlaylistLoader_.media())?this.requestOptions_.timeout=0:this.requestOptions_.timeout=t,"dash"===this.sourceType_&&this.mainPlaylistLoader_.isPaused&&this.mainPlaylistLoader_.load(),this.mainSegmentLoader_.pause(),this.mainSegmentLoader_.playlist(e,this.requestOptions_),this.waitingForFastQualityPlaylistReceived_?this.runFastQualitySwitch_():this.mainSegmentLoader_.load(),this.tech_.trigger({type:"mediachange",bubbles:!0})}),this.mainPlaylistLoader_.on("playlistunchanged",()=>{var e=this.mainPlaylistLoader_.media();"playlist-unchanged"!==e.lastExcludeReason_&&this.stuckAtPlaylistEnd_(e)&&(this.excludePlaylist({error:{message:"Playlist no longer updating.",reason:"playlist-unchanged"}}),this.tech_.trigger("playliststuck"))}),this.mainPlaylistLoader_.on("renditiondisabled",()=>{this.tech_.trigger({type:"usage",name:"vhs-rendition-disabled"})}),this.mainPlaylistLoader_.on("renditionenabled",()=>{this.tech_.trigger({type:"usage",name:"vhs-rendition-enabled"})});["manifestrequeststart","manifestrequestcomplete","manifestparsestart","manifestparsecomplete","playlistrequeststart","playlistrequestcomplete","playlistparsestart","playlistparsecomplete","renditiondisabled","renditionenabled"].forEach(e=>{this.mainPlaylistLoader_.on(e,e=>{this.player_.trigger(f({},e))})})}handleUpdatedMediaPlaylist(e){this.useCueTags_&&this.updateAdCues_(e),this.mainSegmentLoader_.pause(),this.mainSegmentLoader_.playlist(e,this.requestOptions_),this.waitingForFastQualityPlaylistReceived_&&this.runFastQualitySwitch_(),this.updateDuration(!e.endList),this.tech_.paused()||(this.mainSegmentLoader_.load(),this.audioSegmentLoader_&&this.audioSegmentLoader_.load())}triggerPresenceUsage_(e,t){var i=e.mediaGroups||{};let s=!0;var r,e=Object.keys(i.AUDIO);for(r in i.AUDIO)for(var n in i.AUDIO[r])i.AUDIO[r][n].uri||(s=!1);s&&this.tech_.trigger({type:"usage",name:"vhs-demuxed"}),Object.keys(i.SUBTITLES).length&&this.tech_.trigger({type:"usage",name:"vhs-webvtt"}),Uc.Playlist.isAes(t)&&this.tech_.trigger({type:"usage",name:"vhs-aes"}),e.length&&1 `+s.id;if(!e)return l(d+" as current playlist is not set"),!0;if(s.id!==e.id){var h=Boolean(Fd(t,i).length);if(!e.endList)return h||"number"!=typeof e.partTargetDuration?(l(d+" as current playlist is live"),!0):(l(`not ${d} as current playlist is live llhls, but currentTime isn't in buffered.`),!1);h=Vd(t,i),t=o?R.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE:R.MAX_BUFFER_LOW_WATER_LINE;if(a= bufferLowWaterLine (${h} >= ${r})`;return o&&(e+=` and next bandwidth > current bandwidth (${i} > ${a})`),l(e),!0}l(`not ${d} as no switching criteria met`)}}else E.log.warn("We received no playlist to switch to. Please check your stream.");return!1}({buffered:this.tech_.buffered(),currentTime:i,currentPlaylist:t,nextPlaylist:e,bufferLowWaterLine:s,bufferHighWaterLine:r,duration:this.duration(),bufferBasedABR:this.bufferBasedABR,log:this.logger_})}setupSegmentLoaderListeners_(){this.mainSegmentLoader_.on("bandwidthupdate",()=>{this.checkABR_("bandwidthupdate"),this.tech_.trigger("bandwidthupdate")}),this.mainSegmentLoader_.on("timeout",()=>{this.bufferBasedABR&&this.mainSegmentLoader_.load()}),this.bufferBasedABR||this.mainSegmentLoader_.on("progress",()=>{this.trigger("progress")}),this.mainSegmentLoader_.on("error",()=>{var e=this.mainSegmentLoader_.error();this.excludePlaylist({playlistToExclude:e.playlist,error:e})}),this.mainSegmentLoader_.on("appenderror",()=>{this.error=this.mainSegmentLoader_.error_,this.trigger("error")}),this.mainSegmentLoader_.on("syncinfoupdate",()=>{this.onSyncInfoUpdate_()}),this.mainSegmentLoader_.on("timestampoffset",()=>{this.tech_.trigger({type:"usage",name:"vhs-timestamp-offset"})}),this.audioSegmentLoader_.on("syncinfoupdate",()=>{this.onSyncInfoUpdate_()}),this.audioSegmentLoader_.on("appenderror",()=>{this.error=this.audioSegmentLoader_.error_,this.trigger("error")}),this.mainSegmentLoader_.on("ended",()=>{this.logger_("main segment loader ended"),this.onEndOfStream()}),this.timelineChangeController_.on("audioTimelineBehind",()=>{var e=this.audioSegmentLoader_.pendingSegment_;e&&e.segment&&e.segment.syncInfo&&(e=e.segment.syncInfo.end+.01,this.tech_.setCurrentTime(e))}),this.timelineChangeController_.on("fixBadTimelineChange",()=>{this.logger_("Fix bad timeline change. Restarting al segment loaders..."),this.mainSegmentLoader_.pause(),this.mainSegmentLoader_.resetEverything(),this.mediaTypes_.AUDIO.activePlaylistLoader&&(this.audioSegmentLoader_.pause(),this.audioSegmentLoader_.resetEverything()),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&(this.subtitleSegmentLoader_.pause(),this.subtitleSegmentLoader_.resetEverything()),this.load()}),this.mainSegmentLoader_.on("earlyabort",e=>{this.bufferBasedABR||(this.delegateLoaders_("all",["abort"]),this.excludePlaylist({error:{message:"Aborted early because there isn't enough bandwidth to complete the request without rebuffering."},playlistExclusionDuration:10}))});var e=()=>{if(!this.sourceUpdater_.hasCreatedSourceBuffers())return this.tryToCreateSourceBuffers_();var e=this.getCodecsOrExclude_();e&&this.sourceUpdater_.addOrChangeSourceBuffers(e)};this.mainSegmentLoader_.on("trackinfo",e),this.audioSegmentLoader_.on("trackinfo",e),this.mainSegmentLoader_.on("fmp4",()=>{this.triggeredFmp4Usage||(this.tech_.trigger({type:"usage",name:"vhs-fmp4"}),this.triggeredFmp4Usage=!0)}),this.audioSegmentLoader_.on("fmp4",()=>{this.triggeredFmp4Usage||(this.tech_.trigger({type:"usage",name:"vhs-fmp4"}),this.triggeredFmp4Usage=!0)}),this.audioSegmentLoader_.on("ended",()=>{this.logger_("audioSegmentLoader ended"),this.onEndOfStream()});["segmentselected","segmentloadstart","segmentloaded","segmentkeyloadstart","segmentkeyloadcomplete","segmentdecryptionstart","segmentdecryptioncomplete","segmenttransmuxingstart","segmenttransmuxingcomplete","segmenttransmuxingtrackinfoavailable","segmenttransmuxingtiminginfoavailable","segmentappendstart","appendsdone","bandwidthupdated","timelinechange","codecschange"].forEach(e=>{this.mainSegmentLoader_.on(e,e=>{this.player_.trigger(f({},e))}),this.audioSegmentLoader_.on(e,e=>{this.player_.trigger(f({},e))}),this.subtitleSegmentLoader_.on(e,e=>{this.player_.trigger(f({},e))})})}mediaSecondsLoaded_(){return Math.max(this.audioSegmentLoader_.mediaSecondsLoaded+this.mainSegmentLoader_.mediaSecondsLoaded)}load(){this.mainSegmentLoader_.load(),this.mediaTypes_.AUDIO.activePlaylistLoader&&this.audioSegmentLoader_.load(),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&this.subtitleSegmentLoader_.load()}pause(){this.mainSegmentLoader_.pause(),this.mediaTypes_.AUDIO.activePlaylistLoader&&this.audioSegmentLoader_.pause(),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&this.subtitleSegmentLoader_.pause()}fastQualityChange_(e=this.selectPlaylist()){e&&e===this.mainPlaylistLoader_.media()?this.logger_("skipping fastQualityChange because new media is same as old"):(this.switchMedia_(e,"fast-quality"),this.waitingForFastQualityPlaylistReceived_=!0)}runFastQualitySwitch_(){this.waitingForFastQualityPlaylistReceived_=!1,this.mainSegmentLoader_.pause(),this.mainSegmentLoader_.resetEverything(),this.mediaTypes_.AUDIO.activePlaylistLoader&&(this.audioSegmentLoader_.pause(),this.audioSegmentLoader_.resetEverything()),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&(this.subtitleSegmentLoader_.pause(),this.subtitleSegmentLoader_.resetEverything()),this.load()}play(){var e;if(!this.setupFirstPlay())return this.tech_.ended()&&this.tech_.setCurrentTime(0),this.hasPlayed_&&this.load(),e=this.tech_.seekable(),this.tech_.duration()===1/0&&this.tech_.currentTime(){}),this.trigger("sourceopen")}handleSourceEnded_(){var e,t;this.inbandTextTracks_.metadataTrack_&&(e=this.inbandTextTracks_.metadataTrack_.cues)&&e.length&&(t=this.duration(),e[e.length-1].endTime=isNaN(t)||Math.abs(t)===1/0?Number.MAX_VALUE:t)}handleDurationChange_(){this.tech_.trigger("durationchange")}onEndOfStream(){let e=this.mainSegmentLoader_.ended_;var t;this.mediaTypes_.AUDIO.activePlaylistLoader&&(t=this.mainSegmentLoader_.getCurrentMediaInfo_(),e=(t&&!t.hasVideo||e)&&this.audioSegmentLoader_.ended_),e&&(this.stopABRTimer_(),this.sourceUpdater_.endOfStream())}stuckAtPlaylistEnd_(e){var t,i;return!!this.seekable().length&&null!==(t=this.syncController_.getExpiredTime(e,this.duration()))&&(e=Uc.Playlist.playlistEnd(e,t),t=this.tech_.currentTime(),(i=this.tech_.buffered()).length?(i=i.end(i.length-1))-t<=Wd&&e-i<=Wd:e-t<=Wd)}excludePlaylist({playlistToExclude:s=this.mainPlaylistLoader_.media(),error:t={},playlistExclusionDuration:i}){if(s=s||this.mainPlaylistLoader_.media(),i=i||t.playlistExclusionDuration||this.playlistExclusionDuration,s){s.playlistErrors_++;var r=this.mainPlaylistLoader_.main.playlists,n=r.filter(oh),n=1===n.length&&n[0]===s;if(1===r.length&&i!==1/0)return E.log.warn(`Problem encountered with playlist ${s.id}. `+"Trying again since it is the only playlist."),this.tech_.trigger("retryplaylist"),this.mainPlaylistLoader_.load(n);if(n){if(this.main().contentSteering){let e=this.pathwayAttribute_(s);var a=1e3*this.contentSteeringController_.steeringManifest.ttl;return this.contentSteeringController_.excludePathway(e),this.excludeThenChangePathway_(),void setTimeout(()=>{this.contentSteeringController_.addAvailablePathway(e)},a)}let i=!1;r.forEach(e=>{var t;e!==s&&"undefined"!=typeof(t=e.excludeUntil)&&t!==1/0&&(i=!0,delete e.excludeUntil)}),i&&(E.log.warn("Removing other playlists from the exclusion list because the last rendition is about to be excluded."),this.tech_.trigger("retryplaylist"))}let e;e=s.playlistErrors_>this.maxPlaylistRetries?1/0:Date.now()+1e3*i,s.excludeUntil=e,t.reason&&(s.lastExcludeReason_=t.reason),this.tech_.trigger("excludeplaylist"),this.tech_.trigger({type:"usage",name:"vhs-rendition-excluded"});a=this.selectPlaylist();if(a)return(t.internal?this.logger_:E.log.warn)(`${t.internal?"Internal problem":"Problem"} encountered with playlist ${s.id}.`+(t.message?" "+t.message:"")+` Switching to playlist ${a.id}.`),a.attributes.AUDIO!==s.attributes.AUDIO&&this.delegateLoaders_("audio",["abort","pause"]),a.attributes.SUBTITLES!==s.attributes.SUBTITLES&&this.delegateLoaders_("subtitle",["abort","pause"]),this.delegateLoaders_("main",["abort","pause"]),r=a.targetDuration/2*1e3||5e3,i="number"==typeof a.lastRequest&&Date.now()-a.lastRequest<=r,this.switchMedia_(a,"exclude",n||i);this.error="Playback cannot continue. No available working or supported playlists.",this.trigger("error")}else this.error=t,"open"!==this.mediaSource.readyState?this.trigger("error"):this.sourceUpdater_.endOfStream("network")}pauseLoading(){this.delegateLoaders_("all",["abort","pause"]),this.stopABRTimer_()}delegateLoaders_(i,e){let s=[];var t="all"===i,r=(!t&&"main"!==i||s.push(this.mainPlaylistLoader_),[]);!t&&"audio"!==i||r.push("AUDIO"),!t&&"subtitle"!==i||(r.push("CLOSED-CAPTIONS"),r.push("SUBTITLES")),r.forEach(e=>{e=this.mediaTypes_[e]&&this.mediaTypes_[e].activePlaylistLoader;e&&s.push(e)}),["main","audio","subtitle"].forEach(e=>{var t=this[e+"SegmentLoader_"];!t||i!==e&&"all"!==i||s.push(t)}),s.forEach(t=>e.forEach(e=>{"function"==typeof t[e]&&t[e]()}))}setCurrentTime(e){var t=Fd(this.tech_.buffered(),e);return this.mainPlaylistLoader_&&this.mainPlaylistLoader_.media()&&this.mainPlaylistLoader_.media().segments?t&&t.length?e:(this.mainSegmentLoader_.pause(),this.mainSegmentLoader_.resetEverything(),this.mediaTypes_.AUDIO.activePlaylistLoader&&(this.audioSegmentLoader_.pause(),this.audioSegmentLoader_.resetEverything()),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&(this.subtitleSegmentLoader_.pause(),this.subtitleSegmentLoader_.resetEverything()),void this.load()):0}duration(){var e;return this.mainPlaylistLoader_&&(e=this.mainPlaylistLoader_.media())?e.endList?this.mediaSource?this.mediaSource.duration:Uc.Playlist.duration(e):1/0:0}seekable(){return this.seekable_}getSeekableRange_(e,t){var i,s,e=e.media();return e?(t=this.syncController_.getMediaSequenceSync(t))&&t.isReliable?(s=t.start,t=t.end,isFinite(s)&&isFinite(t)?(i=Uc.Playlist.liveEdgeDelay(this.mainPlaylistLoader_.main,e),O([[s,Math.max(s,t-i)]])):null):null!==(s=this.syncController_.getExpiredTime(e,this.duration()))&&(t=Uc.Playlist.seekable(e,s,Uc.Playlist.liveEdgeDelay(this.mainPlaylistLoader_.main,e))).length?t:null:null}computeFinalSeekable_(e,t){var i,s,r;return!t||(i=e.start(0),s=e.end(0),r=t.start(0),t=t.end(0),s{var t,i=this.mediaTypes_[e].groups;for(t in i)i[t].forEach(e=>{e.playlistLoader&&e.playlistLoader.dispose()})}),this.audioSegmentLoader_.dispose(),this.subtitleSegmentLoader_.dispose(),this.sourceUpdater_.dispose(),this.timelineChangeController_.dispose(),this.stopABRTimer_(),this.updateDuration_&&this.mediaSource.removeEventListener("sourceopen",this.updateDuration_),this.mediaSource.removeEventListener("durationchange",this.handleDurationChange_),this.mediaSource.removeEventListener("sourceopen",this.handleSourceOpen_),this.mediaSource.removeEventListener("sourceended",this.handleSourceEnded_),this.off()}main(){return this.mainPlaylistLoader_.main}media(){return this.mainPlaylistLoader_.media()||this.initialMedia_}areMediaTypesKnown_(){var e=!!this.mediaTypes_.AUDIO.activePlaylistLoader,t=!!this.mainSegmentLoader_.getCurrentMediaInfo_(),e=!e||!!this.audioSegmentLoader_.getCurrentMediaInfo_();return t&&e}getCodecsOrExclude_(){let n={main:this.mainSegmentLoader_.getCurrentMediaInfo_()||{},audio:this.audioSegmentLoader_.getCurrentMediaInfo_()||{}},a=this.mainSegmentLoader_.getPendingSegmentPlaylist()||this.media();n.video=n.main;var e=wh(this.main(),a);let o={};var t=!!this.mediaTypes_.AUDIO.activePlaylistLoader;if(n.main.hasVideo&&(o.video=e.video||n.main.videoCodec||"avc1.4d400d"),n.main.isMuxed&&(o.video+=","+(e.audio||n.main.audioCodec||la)),(n.main.hasAudio&&!n.main.isMuxed||n.audio.hasAudio||t)&&(o.audio=e.audio||n.main.audioCodec||n.audio.audioCodec||la,n.audio.isFmp4=(n.main.hasAudio&&!n.main.isMuxed?n.main:n.audio).isFmp4),o.audio||o.video){let i=(e,t)=>e?Jn(t,this.usingManagedMediaSource_):Zn(t),s={},r;if(["video","audio"].forEach(function(e){var t;o.hasOwnProperty(e)&&!i(n[e].isFmp4,o[e])&&(t=n[e].isFmp4?"browser":"muxer",s[t]=s[t]||[],s[t].push(o[e]),"audio"===e)&&(r=t)}),t&&r&&a.attributes.AUDIO){let t=a.attributes.AUDIO;this.main().playlists.forEach(e=>{(e.attributes&&e.attributes.AUDIO)===t&&e!==a&&(e.excludeUntil=1/0)}),this.logger_(`excluding audio group ${t} as ${r} does not support codec(s): "${o.audio}"`)}if(!Object.keys(s).length){if(this.sourceUpdater_.hasCreatedSourceBuffers()&&!this.sourceUpdater_.canChangeType()){let s=[];if(["video","audio"].forEach(e=>{var t=(aa(this.sourceUpdater_.codecs[e]||"")[0]||{}).type,i=(aa(o[e]||"")[0]||{}).type;t&&i&&t.toLowerCase()!==i.toLowerCase()&&s.push(`"${this.sourceUpdater_.codecs[e]}" -> "${o[e]}"`)}),s.length)return void this.excludePlaylist({playlistToExclude:a,error:{message:`Codec switching not supported: ${s.join(", ")}.`,internal:!0},playlistExclusionDuration:1/0})}return o}e=Object.keys(s).reduce((e,t)=>(e&&(e+=", "),e+=`${t} does not support codec(s): "${s[t].join(",")}"`),"")+".",this.excludePlaylist({playlistToExclude:a,error:{internal:!0,message:e},playlistExclusionDuration:1/0})}else this.excludePlaylist({playlistToExclude:a,error:{message:"Could not determine codecs for playlist."},playlistExclusionDuration:1/0})}tryToCreateSourceBuffers_(){var e;"open"!==this.mediaSource.readyState||this.sourceUpdater_.hasCreatedSourceBuffers()||this.areMediaTypesKnown_()&&(e=this.getCodecsOrExclude_())&&(this.sourceUpdater_.createSourceBuffers(e),e=[e.video,e.audio].filter(Boolean).join(","),this.excludeIncompatibleVariants_(e))}excludeUnsupportedVariants_(){let s=this.main().playlists,r=[];Object.keys(s).forEach(e=>{var t,i,e=s[e];-1===r.indexOf(e.id)&&(r.push(e.id),i=[],!(t=wh(this.main,e)).audio||Zn(t.audio)||Jn(t.audio,this.usingManagedMediaSource_)||i.push("audio codec "+t.audio),!t.video||Zn(t.video)||Jn(t.video,this.usingManagedMediaSource_)||i.push("video codec "+t.video),t.text&&"stpp.ttml.im1t"===t.text&&i.push("text codec "+t.text),i.length)&&(e.excludeUntil=1/0,this.logger_(`excluding ${e.id} for unsupported: `+i.join(", ")))})}excludeIncompatibleVariants_(e){let r=[],n=this.main().playlists;e=Ih(aa(e));let a=Sh(e),o=e.video&&aa(e.video)[0]||null,l=e.audio&&aa(e.audio)[0]||null;Object.keys(n).forEach(e=>{var t,i,s,e=n[e];-1===r.indexOf(e.id)&&e.excludeUntil!==1/0&&(r.push(e.id),t=[],s=wh(this.mainPlaylistLoader_.main,e),i=Sh(s),s.audio||s.video)&&(i!==a&&t.push(`codec count "${i}" !== "${a}"`),this.sourceUpdater_.canChangeType()||(i=s.video&&aa(s.video)[0]||null,s=s.audio&&aa(s.audio)[0]||null,i&&o&&i.type.toLowerCase()!==o.type.toLowerCase()&&t.push(`video codec "${i.type}" !== "${o.type}"`),s&&l&&s.type.toLowerCase()!==l.type.toLowerCase()&&t.push(`audio codec "${s.type}" !== "${l.type}"`)),t.length)&&(e.excludeUntil=1/0,this.logger_(`excluding ${e.id}: `+t.join(" && ")))})}updateAdCues_(e){let t=0;var i=this.seekable();i.length&&(t=i.start(0)),function(s,r,e=0){if(s.segments){let t=e,i;for(let e=0;e=s.adStartTime&&t<=s.adEndTime)return s}return null}(r,t+o.duration/2)){if("cueIn"in o){i.endTime=t,i.adEndTime=t,t+=o.duration,i=null;continue}if(t{let r=e.metadataTrack_;if(r){let s=window.WebKitDataCue||window.VTTCue;t.forEach(e=>{for(var t of Object.keys(e)){var i;Gu.has(t)||((i=new s(e.startTime,e.endTime,"")).id=e.id,i.type="com.apple.quicktime.HLS",i.value={key:Wu[t],data:e[t]},"scte35Out"!==t&&"scte35In"!==t||(i.value.data=new Uint8Array(i.value.data.match(/[\da-f]{2}/gi)).buffer),r.addCue(i))}e.processDateRange()})}})({inbandTextTracks:this.inbandTextTracks_,dateRanges:e})}addMetadataToTextTrack(e,t,i){var s=this.sourceUpdater_.videoBuffer?this.sourceUpdater_.videoTimestampOffset():this.sourceUpdater_.audioTimestampOffset();Xu(this.inbandTextTracks_,e,this.tech_),$u({inbandTextTracks:this.inbandTextTracks_,metadataArray:t,timestampOffset:s,videoDuration:i})}pathwayAttribute_(e){return e.attributes["PATHWAY-ID"]||e.attributes.serviceLocation}initContentSteeringController_(){var e=this.main();if(e.contentSteering){for(var t of e.playlists)this.contentSteeringController_.addAvailablePathway(this.pathwayAttribute_(t));this.contentSteeringController_.assignTagProperties(e.uri,e.contentSteering),this.contentSteeringController_.queryBeforeStart?this.contentSteeringController_.requestSteeringManifest(!0):this.tech_.one("canplay",()=>{this.contentSteeringController_.requestSteeringManifest()})}}resetContentSteeringController_(){this.contentSteeringController_.clearAvailablePathways(),this.contentSteeringController_.dispose(),this.initContentSteeringController_()}attachContentSteeringListeners_(){this.contentSteeringController_.on("content-steering",this.excludeThenChangePathway_.bind(this));["contentsteeringloadstart","contentsteeringloadcomplete","contentsteeringparsed"].forEach(e=>{this.contentSteeringController_.on(e,e=>{this.trigger(f({},e))})}),"dash"===this.sourceType_&&this.mainPlaylistLoader_.on("loadedplaylist",()=>{let r=this.main();(this.contentSteeringController_.didDASHTagChange(r.uri,r.contentSteering)||(()=>{var e,t=this.contentSteeringController_.getAvailablePathways(),i=[];for(e of r.playlists){var s=e.attributes.serviceLocation;if(s&&(i.push(s),!t.has(s)))return!0}return!(i.length||!t.size)})())&&this.resetContentSteeringController_()})}excludeThenChangePathway_(){let a=this.contentSteeringController_.getPathway();if(a){this.handlePathwayClones_();let s=this.main().playlists,r=new Set,n=!1;Object.keys(s).forEach(e=>{var e=s[e],t=this.pathwayAttribute_(e),t=t&&a!==t,i=(e.excludeUntil===1/0&&"content-steering"===e.lastExcludeReason_&&!t&&(delete e.excludeUntil,delete e.lastExcludeReason_,n=!0),!e.excludeUntil&&e.excludeUntil!==1/0);!r.has(e.id)&&t&&i&&(r.add(e.id),e.excludeUntil=1/0,e.lastExcludeReason_="content-steering",this.logger_(`excluding ${e.id} for `+e.lastExcludeReason_))}),"DASH"===this.contentSteeringController_.manifestType_&&Object.keys(this.mediaTypes_).forEach(e=>{var e=this.mediaTypes_[e];e.activePlaylistLoader&&(e=e.activePlaylistLoader.media_)&&e.attributes.serviceLocation!==a&&(n=!0)}),n&&this.changeSegmentPathway_()}}handlePathwayClones_(){var i=this.main().playlists,s=this.contentSteeringController_.currentPathwayClones,r=this.contentSteeringController_.nextPathwayClones;if(s&&s.size||r&&r.size){for(var[e,t]of s.entries())r.get(e)||(this.mainPlaylistLoader_.updateOrDeleteClone(t),this.contentSteeringController_.excludePathway(e));for(let[e,t]of r.entries()){var n=s.get(e);n?this.equalPathwayClones_(n,t)||(this.mainPlaylistLoader_.updateOrDeleteClone(t,!0),this.contentSteeringController_.addAvailablePathway(e)):(i.filter(e=>e.attributes["PATHWAY-ID"]===t["BASE-ID"]).forEach(e=>{this.mainPlaylistLoader_.addClonePathway(t,e)}),this.contentSteeringController_.addAvailablePathway(e))}this.contentSteeringController_.currentPathwayClones=new Map(JSON.parse(JSON.stringify([...r])))}}equalPathwayClones_(e,t){if(e["BASE-ID"]!==t["BASE-ID"]||e.ID!==t.ID||e["URI-REPLACEMENT"].HOST!==t["URI-REPLACEMENT"].HOST)return!1;var i,s,r=e["URI-REPLACEMENT"].PARAMS,n=t["URI-REPLACEMENT"].PARAMS;for(i in r)if(r[i]!==n[i])return!1;for(s in n)if(r[s]!==n[s])return!1;return!0}changeSegmentPathway_(){var e=this.selectPlaylist();this.pauseLoading(),"DASH"===this.contentSteeringController_.manifestType_&&this.switchMediaForDASHContentSteering_(),this.switchMedia_(e,"content-steering")}excludeNonUsablePlaylistsByKeyId_(){if(this.mainPlaylistLoader_&&this.mainPlaylistLoader_.main){let r=0,n="non-usable";this.mainPlaylistLoader_.main.playlists.forEach(s=>{var e=this.mainPlaylistLoader_.getKeyIdSet(s);e&&e.size&&e.forEach(e=>{var t="usable",t=this.keyStatusMap_.has(e)&&this.keyStatusMap_.get(e)===t,i=s.lastExcludeReason_===n&&s.excludeUntil===1/0;t?i&&(delete s.excludeUntil,delete s.lastExcludeReason_,this.logger_(`enabling playlist ${s.id} because key ID ${e} is usable`)):(s.excludeUntil!==1/0&&s.lastExcludeReason_!==n&&(s.excludeUntil=1/0,s.lastExcludeReason_=n,this.logger_(`excluding playlist ${s.id} because the key ID ${e} doesn't exist in the keyStatusMap or is not usable`)),r++)})}),r>=this.mainPlaylistLoader_.main.playlists.length&&this.mainPlaylistLoader_.main.playlists.forEach(e=>{var t=e&&e.attributes&&e.attributes.RESOLUTION&&e.attributes.RESOLUTION.height<720,i=e.excludeUntil===1/0&&e.lastExcludeReason_===n;t&&i&&(delete e.excludeUntil,E.log.warn(`enabling non-HD playlist ${e.id} because all playlists were excluded due to ${n} key IDs`))})}}addKeyStatus_(e,t){e=("string"==typeof e?e:(e=>{e=new Uint8Array(e);return Array.from(e).map(e=>e.toString(16).padStart(2,"0")).join("")})(e)).slice(0,32).toLowerCase();this.logger_(`KeyStatus '${t}' with key ID ${e} added to the keyStatusMap`),this.keyStatusMap_.set(e,t)}updatePlaylistByKeyStatus(e,t){this.addKeyStatus_(e,t),this.waitingForFastQualityPlaylistReceived_||this.excludeNonUsableThenChangePlaylist_(),this.mainPlaylistLoader_.off("loadedplaylist",this.excludeNonUsableThenChangePlaylist_.bind(this)),this.mainPlaylistLoader_.on("loadedplaylist",this.excludeNonUsableThenChangePlaylist_.bind(this))}excludeNonUsableThenChangePlaylist_(){this.excludeNonUsablePlaylistsByKeyId_(),this.fastQualityChange_()}}class qc{constructor(e,t,i){var s,n,a,o,r=e.playlistController_,l=r.fastQualityChange_.bind(r);t.attributes&&(s=t.attributes.RESOLUTION,this.width=s&&s.width,this.height=s&&s.height,this.bandwidth=t.attributes.BANDWIDTH,this.frameRate=t.attributes["FRAME-RATE"]),this.codecs=wh(r.main(),t),this.playlist=t,this.id=i,this.enabled=(n=e.playlists,a=t.id,o=l,e=>{var t=n.main.playlists[a],i=ah(t),s=oh(t);if("undefined"==typeof e)return s;e?delete t.disabled:t.disabled=!0;var r={renditionInfo:{id:a,bandwidth:t.attributes.BANDWIDTH,resolution:t.attributes.RESOLUTION,codecs:t.attributes.CODECS},cause:"fast-quality"};return e===s||i||(e?(o(t),n.trigger({type:"renditionenabled",metadata:r})):n.trigger({type:"renditiondisabled",metadata:r})),e})}}let jc=["seeking","seeked","pause","playing","error"];class Vc extends E.EventTarget{constructor(e){super(),this.playlistController_=e.playlistController,this.tech_=e.tech,this.seekable=e.seekable,this.allowSeeksWithinUnsafeLiveWindow=e.allowSeeksWithinUnsafeLiveWindow,this.liveRangeSafeTimeDelta=e.liveRangeSafeTimeDelta,this.media=e.media,this.playedRanges_=[],this.consecutiveUpdates=0,this.lastRecordedTime=null,this.checkCurrentTimeTimeout_=null,this.logger_=Bd("PlaybackWatcher"),this.logger_("initialize");let t=()=>this.monitorCurrentTime_(),i=()=>this.monitorCurrentTime_(),s=()=>this.techWaiting_(),r=()=>this.resetTimeUpdate_(),n=this.playlistController_,a=["main","subtitle","audio"],o={},l=(a.forEach(e=>{o[e]={reset:()=>this.resetSegmentDownloads_(e),updateend:()=>this.checkSegmentDownloads_(e)},n[e+"SegmentLoader_"].on("appendsdone",o[e].updateend),n[e+"SegmentLoader_"].on("playlistupdate",o[e].reset),this.tech_.on(["seeked","seeking"],o[e].reset)}),t=>{["main","audio"].forEach(e=>{n[e+"SegmentLoader_"][t]("appended",this.seekingAppendCheck_)})});this.seekingAppendCheck_=()=>{this.fixesBadSeeks_()&&(this.consecutiveUpdates=0,this.lastRecordedTime=this.tech_.currentTime(),l("off"))},this.clearSeekingAppendCheck_=()=>l("off"),this.watchForBadSeeking_=()=>{this.clearSeekingAppendCheck_(),l("on")},this.tech_.on("seeked",this.clearSeekingAppendCheck_),this.tech_.on("seeking",this.watchForBadSeeking_),this.tech_.on("waiting",s),this.tech_.on(jc,r),this.tech_.on("canplay",i),this.tech_.one("play",t),this.dispose=()=>{this.clearSeekingAppendCheck_(),this.logger_("dispose"),this.tech_.off("waiting",s),this.tech_.off(jc,r),this.tech_.off("canplay",i),this.tech_.off("play",t),this.tech_.off("seeking",this.watchForBadSeeking_),this.tech_.off("seeked",this.clearSeekingAppendCheck_),a.forEach(e=>{n[e+"SegmentLoader_"].off("appendsdone",o[e].updateend),n[e+"SegmentLoader_"].off("playlistupdate",o[e].reset),this.tech_.off(["seeked","seeking"],o[e].reset)}),this.checkCurrentTimeTimeout_&&window.clearTimeout(this.checkCurrentTimeTimeout_),this.resetTimeUpdate_()}}monitorCurrentTime_(){this.checkCurrentTime_(),this.checkCurrentTimeTimeout_&&window.clearTimeout(this.checkCurrentTimeTimeout_),this.checkCurrentTimeTimeout_=window.setTimeout(this.monitorCurrentTime_.bind(this),250)}resetSegmentDownloads_(e){var t=this.playlistController_[e+"SegmentLoader_"];0=t.end(t.length-1))?this.techWaiting_():void(5<=this.consecutiveUpdates&&e===this.lastRecordedTime?(this.consecutiveUpdates++,this.waiting_()):e===this.lastRecordedTime?this.consecutiveUpdates++:(this.playedRanges_.push(O([this.lastRecordedTime,e])),t={playedRanges:this.playedRanges_},this.playlistController_.trigger({type:"playedrangeschanged",metadata:t}),this.consecutiveUpdates=0,this.lastRecordedTime=e))}resetTimeUpdate_(){this.consecutiveUpdates=0}fixesBadSeeks_(){if(!this.tech_.seeking())return!1;var e=this.seekable(),t=this.tech_.currentTime();let i;if(this.afterSeekableWindow_(e,t,this.media(),this.allowSeeksWithinUnsafeLiveWindow)&&(s=e.end(e.length-1),i=s),this.beforeSeekableWindow_(e,t)&&(s=e.start(0),i=s+(s===e.end(0)?0:Wd)),"undefined"!=typeof i)this.logger_(`Trying to seek outside of seekable at time ${t} with `+`seekable range ${Xd(e)}. Seeking to `+i+".");else{var s=this.playlistController_.sourceUpdater_,e=this.tech_.buffered(),r=s.audioBuffer?s.audioBuffered():null,s=s.videoBuffer?s.videoBuffered():null,n=this.media(),a=n.partTargetDuration||2*(n.targetDuration-$d),o=[r,s];for(let e=0;e ${t.end(0)}]. Attempting to resume `+"playback by seeking to the current time."),this.tech_.trigger({type:"usage",name:"vhs-unknown-waiting"})))}techWaiting_(){var e,t=this.seekable(),i=this.tech_.currentTime();return!!this.tech_.seeking()||(this.beforeSeekableWindow_(t,i)?(t=t.end(t.length-1),this.logger_(`Fell out of live window at time ${i}. Seeking to `+"live point (seekable end) "+t),this.resetTimeUpdate_(),this.tech_.setCurrentTime(t),this.tech_.trigger({type:"usage",name:"vhs-live-resync"}),!0):(t=this.tech_.vhs.playlistController_.sourceUpdater_,e=this.tech_.buffered(),this.videoUnderflow_({audioBuffered:t.audioBuffered(),videoBuffered:t.videoBuffered(),currentTime:i})?(this.resetTimeUpdate_(),this.tech_.setCurrentTime(i),this.tech_.trigger({type:"usage",name:"vhs-video-underflow"}),!0):0<(t=qd(e,i)).length&&(this.logger_(`Stopped at ${i} and seeking to `+t.start(0)),this.resetTimeUpdate_(),this.skipTheGap_(i),!0)))}afterSeekableWindow_(e,t,i,s=!1){if(!e.length)return!1;let r=e.end(e.length-1)+Wd;var n=!i.endList;return t>(r=n&&("number"==typeof i.partTargetDuration||s)?e.end(e.length-1)+3*i.targetDuration:r)}beforeSeekableWindow_(e,t){return!!(e.length&&0{t.trigger({type:"usage",name:"vhs-error-reload-initialized"})}),function(){a&&t.currentTime(a)});t.on("error",s),t.on("dispose",r),t.reloadSourceOnError=function(e){r(),zc(t,e)}};function $c(t,e){var i=e.media();let s=-1;for(let e=0;eTu(e,t)),e.filter(e=>!!wh(this.playlists.main,e).video));return e[0]||null},lastBandwidthSelector:Vu,movingAverageBandwidthSelector:function(t){let i=-1,s=-1;if(t<0||1{Object.defineProperty(N,t,{get(){return E.log.warn(`using Vhs.${t} is UNSAFE be sure you know what you are doing`),R[t]},set(e){E.log.warn(`using Vhs.${t} is UNSAFE be sure you know what you are doing`),"number"!=typeof e||e<0?E.log.warn(`value of Vhs.${t} must be greater than or equal to 0`):R[t]=e}})}),"videojs-vhs"),Gc=(N.canPlaySource=function(){return E.log.warn("VHS is no longer a tech. Please remove it from your player's techOrder.")},({player:s,sourceKeySystems:e,audioMedia:t,mainPlaylists:i})=>{if(!s.eme.initializeMediaKeys)return Promise.resolve();var r,t=t?i.concat([t]):i,t=(i=t,r=Object.keys(e),i.reduce((e,s)=>{var t;return s.contentProtection&&(t=r.reduce((e,t)=>{var i=s.contentProtection[t];return i&&i.pssh&&(e[t]={pssh:i.pssh}),e},{}),Object.keys(t).length)&&e.push(t),e},[]));let n=[],a=[];return t.forEach(e=>{a.push(new Promise((e,t)=>{s.tech_.one("keysessioncreated",e)})),n.push(new Promise((t,i)=>{s.eme.initializeMediaKeys({keySystems:e},e=>{e?i(e):t()})}))}),Promise.race([Promise.all(n),Promise.race(a)])}),Xc=({player:e,sourceKeySystems:t,media:i,audioMedia:s})=>{t=((e,t,i)=>{if(!e)return e;let s={};t&&t.attributes&&t.attributes.CODECS&&(s=Ih(aa(t.attributes.CODECS))),i&&i.attributes&&i.attributes.CODECS&&(s.audio=i.attributes.CODECS);var r,n=oa(s.video),a=oa(s.audio),o={};for(r in e)o[r]={},a&&(o[r].audioContentType=a),n&&(o[r].videoContentType=n),t.contentProtection&&t.contentProtection[r]&&t.contentProtection[r].pssh&&(o[r].pssh=t.contentProtection[r].pssh),"string"==typeof e[r]&&(o[r].url=e[r]);return L(e,o)})(t,i,s);return!(!t||(e.currentSource().keySystems=t)&&!e.eme&&(E.log.warn("DRM encrypted source cannot be decrypted without a DRM plugin"),1))},Kc=()=>{if(!window.localStorage)return null;var e=window.localStorage.getItem(Wc);if(!e)return null;try{return JSON.parse(e)}catch(e){return null}},Yc=(e,t)=>{e._requestCallbackSet||(e._requestCallbackSet=new Set),e._requestCallbackSet.add(t)},Qc=(e,t)=>{e._responseCallbackSet||(e._responseCallbackSet=new Set),e._responseCallbackSet.add(t)},Jc=(e,t)=>{e._requestCallbackSet&&(e._requestCallbackSet.delete(t),e._requestCallbackSet.size||delete e._requestCallbackSet)},Zc=(e,t)=>{e._responseCallbackSet&&(e._responseCallbackSet.delete(t),e._responseCallbackSet.size||delete e._responseCallbackSet)};N.supportsNativeHls=function(){if(!document||!document.createElement)return!1;let t=document.createElement("video");return!!E.getTech("Html5").isSupported()&&["application/vnd.apple.mpegurl","audio/mpegurl","audio/x-mpegurl","application/x-mpegurl","video/x-mpegurl","video/mpegurl","application/mpegurl"].some(function(e){return/maybe|probably/i.test(t.canPlayType(e))})}(),N.supportsNativeDash=!!(document&&document.createElement&&E.getTech("Html5").isSupported())&&/maybe|probably/i.test(document.createElement("video").canPlayType("application/dash+xml")),N.supportsTypeNatively=e=>"hls"===e?N.supportsNativeHls:"dash"===e&&N.supportsNativeDash,N.isSupported=function(){return E.log.warn("VHS is no longer a tech. Please remove it from your player's techOrder.")},N.xhr.onRequest=function(e){Yc(N.xhr,e)},N.xhr.onResponse=function(e){Qc(N.xhr,e)},N.xhr.offRequest=function(e){Jc(N.xhr,e)},N.xhr.offResponse=function(e){Zc(N.xhr,e)};t=E.getComponent("Component");class ep extends t{constructor(e,t,i){if(super(t,i.vhs),"number"==typeof i.initialBandwidth&&(this.options_.bandwidth=i.initialBandwidth),this.logger_=Bd("VhsHandler"),t.options_&&t.options_.playerId&&(i=E.getPlayer(t.options_.playerId),this.player_=i),this.tech_=t,this.source_=e,this.stats={},this.ignoreNextSeekingEvent_=!1,this.setOptions_(),this.options_.overrideNative&&t.overrideNativeAudioTracks&&t.overrideNativeVideoTracks)t.overrideNativeAudioTracks(!0),t.overrideNativeVideoTracks(!0);else if(this.options_.overrideNative&&(t.featuresNativeVideoTracks||t.featuresNativeAudioTracks))throw new Error("Overriding native VHS requires emulated tracks. See https://git.io/vMpjB");this.on(document,["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"],e=>{var t=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;t&&t.contains(this.tech_.el())?this.playlistController_.fastQualityChange_():this.playlistController_.checkABR_()}),this.on(this.tech_,"seeking",function(){this.ignoreNextSeekingEvent_?this.ignoreNextSeekingEvent_=!1:this.setCurrentTime(this.tech_.currentTime())}),this.on(this.tech_,"error",function(){this.tech_.error()&&this.playlistController_&&this.playlistController_.pauseLoading()}),this.on(this.tech_,"play",this.play)}setOptions_(e={}){this.options_=L(this.options_,e),this.options_.withCredentials=this.options_.withCredentials||!1,this.options_.limitRenditionByPlayerDimensions=!1!==this.options_.limitRenditionByPlayerDimensions,this.options_.useDevicePixelRatio=this.options_.useDevicePixelRatio||!1,this.options_.usePlayerObjectFit=this.options_.usePlayerObjectFit||!1,this.options_.useBandwidthFromLocalStorage="undefined"!=typeof this.source_.useBandwidthFromLocalStorage?this.source_.useBandwidthFromLocalStorage:this.options_.useBandwidthFromLocalStorage||!1,this.options_.useForcedSubtitles=this.options_.useForcedSubtitles||!1,this.options_.useNetworkInformationApi="undefined"==typeof this.options_.useNetworkInformationApi||this.options_.useNetworkInformationApi,this.options_.useDtsForTimestampOffset=this.options_.useDtsForTimestampOffset||!1,this.options_.customTagParsers=this.options_.customTagParsers||[],this.options_.customTagMappers=this.options_.customTagMappers||[],this.options_.cacheEncryptionKeys=this.options_.cacheEncryptionKeys||!1,this.options_.llhls=!1!==this.options_.llhls,this.options_.bufferBasedABR=this.options_.bufferBasedABR||!1,"number"!=typeof this.options_.playlistExclusionDuration&&(this.options_.playlistExclusionDuration=60),"number"!=typeof this.options_.bandwidth&&this.options_.useBandwidthFromLocalStorage&&((e=Kc())&&e.bandwidth&&(this.options_.bandwidth=e.bandwidth,this.tech_.trigger({type:"usage",name:"vhs-bandwidth-from-local-storage"})),e)&&e.throughput&&(this.options_.throughput=e.throughput,this.tech_.trigger({type:"usage",name:"vhs-throughput-from-local-storage"})),"number"!=typeof this.options_.bandwidth&&(this.options_.bandwidth=R.INITIAL_BANDWIDTH),this.options_.enableLowInitialPlaylist=this.options_.enableLowInitialPlaylist&&this.options_.bandwidth===R.INITIAL_BANDWIDTH,["withCredentials","useDevicePixelRatio","usePlayerObjectFit","customPixelRatio","limitRenditionByPlayerDimensions","bandwidth","customTagParsers","customTagMappers","cacheEncryptionKeys","playlistSelector","initialPlaylistSelector","bufferBasedABR","liveRangeSafeTimeDelta","llhls","useForcedSubtitles","useNetworkInformationApi","useDtsForTimestampOffset","exactManifestTimings","leastPixelDiffSelector"].forEach(e=>{"undefined"!=typeof this.source_[e]&&(this.options_[e]=this.source_[e])}),this.limitRenditionByPlayerDimensions=this.options_.limitRenditionByPlayerDimensions,this.useDevicePixelRatio=this.options_.useDevicePixelRatio,this.usePlayerObjectFit=this.options_.usePlayerObjectFit;e=this.options_.customPixelRatio;"number"==typeof e&&0<=e&&(this.customPixelRatio=e)}setOptions(e={}){this.setOptions_(e)}src(e,t){e&&(this.setOptions_(),this.options_.src=0===(e=this.source_.src).toLowerCase().indexOf("data:application/vnd.videojs.vhs+json,")?JSON.parse(e.substring(e.indexOf(",")+1)):e,this.options_.tech=this.tech_,this.options_.externVhs=N,this.options_.sourceType=ea(t),this.options_.seekTo=e=>{this.tech_.setCurrentTime(e)},this.options_.player_=this.player_,this.playlistController_=new Fc(this.options_),e=L({liveRangeSafeTimeDelta:Wd},this.options_,{seekable:()=>this.seekable(),media:()=>this.playlistController_.media(),playlistController:this.playlistController_}),this.playbackWatcher_=new Vc(e),this.attachStreamingEventListeners_(),this.playlistController_.on("error",()=>{var e=E.players[this.tech_.options_.playerId];let t=this.playlistController_.error;"object"!=typeof t||t.code?"string"==typeof t&&(t={message:t,code:3}):t.code=3,e.error(t)}),t=this.options_.bufferBasedABR?N.movingAverageBandwidthSelector(.55):N.STANDARD_PLAYLIST_SELECTOR,this.playlistController_.selectPlaylist=(this.selectPlaylist||t).bind(this),this.playlistController_.selectInitialPlaylist=N.INITIAL_PLAYLIST_SELECTOR.bind(this),this.playlists=this.playlistController_.mainPlaylistLoader_,this.mediaSource=this.playlistController_.mediaSource,Object.defineProperties(this,{selectPlaylist:{get(){return this.playlistController_.selectPlaylist},set(e){this.playlistController_.selectPlaylist=e.bind(this)}},throughput:{get(){return this.playlistController_.mainSegmentLoader_.throughput.rate},set(e){this.playlistController_.mainSegmentLoader_.throughput.rate=e,this.playlistController_.mainSegmentLoader_.throughput.count=1}},bandwidth:{get(){let e=this.playlistController_.mainSegmentLoader_.bandwidth;var t=window.navigator.connection||window.navigator.mozConnection||window.navigator.webkitConnection;return this.options_.useNetworkInformationApi&&t&&(t=1e3*t.downlink*1e3,e=1e7<=t&&1e7<=e?Math.max(e,t):t),e},set(e){this.playlistController_.mainSegmentLoader_.bandwidth=e,this.playlistController_.mainSegmentLoader_.throughput={rate:0,count:0}}},systemBandwidth:{get(){var e=1/(this.bandwidth||1);let t;return t=0this.bandwidth||0,enumerable:!0},mediaRequests:{get:()=>this.playlistController_.mediaRequests_()||0,enumerable:!0},mediaRequestsAborted:{get:()=>this.playlistController_.mediaRequestsAborted_()||0,enumerable:!0},mediaRequestsTimedout:{get:()=>this.playlistController_.mediaRequestsTimedout_()||0,enumerable:!0},mediaRequestsErrored:{get:()=>this.playlistController_.mediaRequestsErrored_()||0,enumerable:!0},mediaTransferDuration:{get:()=>this.playlistController_.mediaTransferDuration_()||0,enumerable:!0},mediaBytesTransferred:{get:()=>this.playlistController_.mediaBytesTransferred_()||0,enumerable:!0},mediaSecondsLoaded:{get:()=>this.playlistController_.mediaSecondsLoaded_()||0,enumerable:!0},mediaAppends:{get:()=>this.playlistController_.mediaAppends_()||0,enumerable:!0},mainAppendsToLoadedData:{get:()=>this.playlistController_.mainAppendsToLoadedData_()||0,enumerable:!0},audioAppendsToLoadedData:{get:()=>this.playlistController_.audioAppendsToLoadedData_()||0,enumerable:!0},appendsToLoadedData:{get:()=>this.playlistController_.appendsToLoadedData_()||0,enumerable:!0},timeToLoadedData:{get:()=>this.playlistController_.timeToLoadedData_()||0,enumerable:!0},buffered:{get:()=>Kd(this.tech_.buffered()),enumerable:!0},currentTime:{get:()=>this.tech_.currentTime(),enumerable:!0},currentSource:{get:()=>this.tech_.currentSource_,enumerable:!0},currentTech:{get:()=>this.tech_.name_,enumerable:!0},duration:{get:()=>this.tech_.duration(),enumerable:!0},main:{get:()=>this.playlists.main,enumerable:!0},playerDimensions:{get:()=>this.tech_.currentDimensions(),enumerable:!0},seekable:{get:()=>Kd(this.tech_.seekable()),enumerable:!0},timestamp:{get:()=>Date.now(),enumerable:!0},videoPlaybackQuality:{get:()=>this.tech_.getVideoPlaybackQuality(),enumerable:!0}}),this.tech_.one("canplay",this.playlistController_.setupFirstPlay.bind(this.playlistController_)),this.tech_.on("bandwidthupdate",()=>{if(this.options_.useBandwidthFromLocalStorage){var e={bandwidth:this.bandwidth,throughput:Math.round(this.throughput)};if(window.localStorage){var t=(t=Kc())?L(t,e):e;try{window.localStorage.setItem(Wc,JSON.stringify(t))}catch(e){return}}}}),this.playlistController_.on("selectedinitialmedia",()=>{var i;(i=this).representations=()=>{var e=i.playlistController_.main(),e=ch(e)?i.playlistController_.getAudioTrackPlaylists_():e.playlists;return e?e.filter(e=>!ah(e)).map((e,t)=>new qc(i,e,e.id)):[]}}),this.playlistController_.sourceUpdater_.on("createdsourcebuffers",()=>{this.setupEme_()}),this.on(this.playlistController_,"progress",function(){this.tech_.trigger("progress")}),this.on(this.playlistController_,"firstplay",function(){this.ignoreNextSeekingEvent_=!0}),this.setupQualityLevels_(),this.tech_.el())&&(this.mediaSourceUrl_=window.URL.createObjectURL(this.playlistController_.mediaSource),(E.browser.IS_ANY_SAFARI||E.browser.IS_IOS)&&this.options_.overrideNative&&"hls"===this.options_.sourceType&&"function"==typeof this.tech_.addSourceElement?(this.tech_.addSourceElement(this.mediaSourceUrl_),this.tech_.addSourceElement(this.source_.src)):this.tech_.src(this.mediaSourceUrl_))}createKeySessions_(){var e=this.playlistController_.mediaTypes_.AUDIO.activePlaylistLoader;this.logger_("waiting for EME key session creation"),Gc({player:this.player_,sourceKeySystems:this.source_.keySystems,audioMedia:e&&e.media(),mainPlaylists:this.playlists.main.playlists}).then(()=>{this.logger_("created EME key session"),this.playlistController_.sourceUpdater_.initializedEme()}).catch(e=>{this.logger_("error while creating EME key session",e),this.player_.error({message:"Failed to initialize media keys for EME",code:3})})}handleWaitingForKey_(){this.logger_("waitingforkey fired, attempting to create any new key sessions"),this.createKeySessions_()}setupEme_(){var e=this.playlistController_.mediaTypes_.AUDIO.activePlaylistLoader,e=Xc({player:this.player_,sourceKeySystems:this.source_.keySystems,media:this.playlists.media(),audioMedia:e&&e.media()});this.player_.tech_.on("keystatuschange",e=>{this.playlistController_.updatePlaylistByKeyStatus(e.keyId,e.status)}),this.handleWaitingForKey_=this.handleWaitingForKey_.bind(this),this.player_.tech_.on("waitingforkey",this.handleWaitingForKey_),e?this.createKeySessions_():this.playlistController_.sourceUpdater_.initializedEme()}setupQualityLevels_(){var e=E.players[this.tech_.options_.playerId];e&&e.qualityLevels&&!this.qualityLevels_&&(this.qualityLevels_=e.qualityLevels(),this.playlistController_.on("selectedinitialmedia",()=>{var t,e;t=this.qualityLevels_,(e=this).representations().forEach(e=>{t.addQualityLevel(e)}),$c(t,e.playlists)}),this.playlists.on("mediachange",()=>{$c(this.qualityLevels_,this.playlists)}))}static version(){return{"@videojs/http-streaming":"3.17.2","mux.js":"7.1.0","mpd-parser":"1.3.1","m3u8-parser":"7.2.0","aes-decrypter":"4.0.2"}}version(){return this.constructor.version()}canChangeType(){return mc.canChangeType()}play(){this.playlistController_.play()}setCurrentTime(e){this.playlistController_.setCurrentTime(e)}duration(){return this.playlistController_.duration()}seekable(){return this.playlistController_.seekable()}dispose(){this.playbackWatcher_&&this.playbackWatcher_.dispose(),this.playlistController_&&this.playlistController_.dispose(),this.qualityLevels_&&this.qualityLevels_.dispose(),this.tech_&&this.tech_.vhs&&delete this.tech_.vhs,this.mediaSourceUrl_&&window.URL.revokeObjectURL&&(window.URL.revokeObjectURL(this.mediaSourceUrl_),this.mediaSourceUrl_=null),this.tech_&&this.tech_.off("waitingforkey",this.handleWaitingForKey_),super.dispose()}convertToProgramTime(e,t){return Gh({playlist:this.playlistController_.media(),time:e,callback:t})}seekToProgramTime(e,t,i=!0,s=2){return Xh({programTime:e,playlist:this.playlistController_.media(),retryCount:s,pauseAfterSeek:i,seekTo:this.options_.seekTo,tech:this.options_.tech,callback:t})}setupXhrHooks_(){this.xhr.onRequest=e=>{Yc(this.xhr,e)},this.xhr.onResponse=e=>{Qc(this.xhr,e)},this.xhr.offRequest=e=>{Jc(this.xhr,e)},this.xhr.offResponse=e=>{Zc(this.xhr,e)},this.player_.trigger("xhr-hooks-ready")}attachStreamingEventListeners_(){["seekablerangeschanged","bufferedrangeschanged","contentsteeringloadstart","contentsteeringloadcomplete","contentsteeringparsed"].forEach(e=>{this.playlistController_.on(e,e=>{this.player_.trigger(f({},e))})}),["gapjumped","playedrangeschanged"].forEach(e=>{this.playbackWatcher_.on(e,e=>{this.player_.trigger(f({},e))})})}}let tp={name:"videojs-http-streaming",VERSION:"3.17.2",canHandleSource(e,t={}){t=L(E.options,t);return!(!t.vhs.experimentalUseMMS&&!Jn("avc1.4d400d,mp4a.40.2",!1))&&tp.canPlayType(e.type,t)},handleSource(e,t,i={}){i=L(E.options,i);return t.vhs=new ep(e,t,i),t.vhs.xhr=Uh(),t.vhs.setupXhrHooks_(),t.vhs.src(e.src,e.type),t.vhs},canPlayType(e,t){e=ea(e);return e&&(t=tp.getOverrideNative(t),!N.supportsTypeNatively(e)||t)?"maybe":""},getOverrideNative(e={}){var{vhs:e={}}=e,t=!(E.browser.IS_ANY_SAFARI||E.browser.IS_IOS),{overrideNative:e=t}=e;return e}};return Jn("avc1.4d400d,mp4a.40.2",!0)&&E.getTech("Html5").registerSourceHandler(tp,0),E.VhsHandler=ep,E.VhsSourceHandler=tp,E.Vhs=N,E.use||E.registerComponent("Vhs",N),E.options.vhs=E.options.vhs||{},E.getPlugin&&E.getPlugin("reloadSourceOnError")||E.registerPlugin("reloadSourceOnError",function(e){zc(this,e)}),E}); \ No newline at end of file diff --git a/view/templates/hls_top.tpl b/view/templates/content/hls.tpl similarity index 96% rename from view/templates/hls_top.tpl rename to view/templates/content/hls.tpl index 9a4b124729..8448da50e0 100644 --- a/view/templates/hls_top.tpl +++ b/view/templates/content/hls.tpl @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later *}} -
          +