]> git.gir.st - subscriptionfeed.git/blob - app/youtube/templates/watch.html.j2
add final / to /channel/ urls in templates
[subscriptionfeed.git] / app / youtube / templates / watch.html.j2
1 {% extends "base.html.j2" %}
2 {% import 'macros.imp.j2' as macros %}
3
4 {% block title %}{{ title | e }} — {{ author | e }}{% endblock %}
5
6 {% block content %}
7 {% if video_url %}
8 <div class="aspect-ratio main-video" style="--aspect-ratio:{{ aspectr }}">
9 <video controls poster="{{ poster }}">
10 {% for v in stream_map.muxed|sort(attribute='height', reverse=True) %}
11 <source src="{{v.url}}">
12 {% endfor %}
13 {% set cc_default = False %}
14 {% for cc in subtitles %}
15 <track label="{{ cc.name }}" kind="subtitles" srclang="{{ cc.code }}" src="{{ url_for('youtube.timedtext') }}?{{ cc.query }}" {{ 'default' if cc_default and not loop.counter }}>
16 {% endfor %}
17 </video>
18
19 <script>
20 "use strict";
21 //todo: should only be done after user is made aware of video id getting sent to 3rd party (wait for k-anon)
22 //window.addEventListener("load", () => load_sponsorblock("{{ video_id }}"));
23 document.addEventListener('DOMContentLoaded', ()=>{ let check = document.querySelector("#skip_sponsors");
24 check.addEventListener("change", () => {if (check.checked) load_sponsorblock("{{ video_id }}")});});
25 function load_sponsorblock(video_id){
26 fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${video_id}`)
27 .then(response => response.json())
28 .then(data => {
29 for (const segment of data) {
30 const [start, stop] = segment.segment;
31 if (segment.category != "sponsor") continue;
32 document.querySelector('.main-video video')
33 .addEventListener("timeupdate", function() {
34 if (document.querySelector("#skip_sponsors").checked &&
35 this.currentTime >= start && this.currentTime < stop-1) {
36 this.currentTime = stop;
37 }
38 });
39 }
40 });
41 }
42 </script>
43
44 </div>
45 {% else %}{#TODO: this'll break livestreams #}
46 <img src="{{ poster }}" style="width:100%;object-fit:cover;height:calc(100% / {{ aspectr }});">
47 {% endif %}
48
49 {% if video_error %}
50 <div class="video_error">
51 {{ errdetails }} Watch on <a href="{{ invidious_url }}">Invidious</a> or <a href="https://www.youtube.com/watch?v={{ video_id }}">Youtube</a>
52 </div>
53 {% endif %}
54
55 <h1>{{ title | e }}<br>
56 <small><a href="/channel/{{ channel_id }}/">{{ author | e }}</a></small></h1>
57
58 <details><summary>Description</summary>
59 <p style="white-space:pre-wrap">{{ description | e }}
60 <hr></details>
61
62 <details><summary>Metadata</summary>
63 <dl>
64 <dt>Duration
65 <dd>{{ length | format_time }}
66 <dt>Views
67 <dd>{{ '{0:,}'.format(views | int)|replace(",","&thinsp;") }}
68 <dt>Published
69 <dd>{{ published.split('T')[0] }}
70 <dt>Rating
71 <dd>{{ rating | round(1) }}/5
72 <dt>Visibility
73 <dd>{{ 'unlisted' if unlisted else 'public' }}
74 {% if blacklisted|length == 0 %}
75 <dt>Available in
76 <dd>all regions
77 {% elif whitelisted|length == 0 %}
78 <dt>Blacklisted in
79 <dd>all regions
80 {% elif blacklisted|length > whitelisted|length %}
81 <dt>Available in
82 <dd>{{ whitelisted | join(', ') }}
83 {% else %}
84 <dt>Blacklisted in
85 <dd>{{ blacklisted | join(', ') }}
86 {% endif %}
87 </dl>
88 <hr></details>
89
90 <details><summary>More Actions</summary>
91 <ul class="more-actions">
92 <li><label><input type=checkbox id=skip_sponsors>skip sponsors</label>
93 {# TODO: make checked by default (need to inform the user about potential privacy concerns) #}
94 <noscript><br>Note: requires javascript</noscript>
95 {# TODO: don't redirect away (204 response?) #}
96 <li>{{ macros.emoji_link("audio", video_id, True) }}
97 <li>{{ macros.emoji_button("pin", video_id, is_pinned, True) }}
98 <li>{{ macros.emoji_button("subscribe", channel_id, is_subscribed, True) }}
99 <li>{{ macros.emoji_link("raw", video_id, True) }}
100 <li>{{ macros.emoji_link("json", video_id, True) }}
101 <li><a href="https://invidio.us/watch?v={{ video_id }}">watch on invidious</a>
102 <li><a href="https://youtu.be/{{ video_id }}">watch on youtube</a>
103 </ul>
104 <hr></details>
105
106 <details><summary>Info- and Endcards</summary>
107 <div class="cards">
108 {% for card in all_cards %} {# Note: no point in displaying the current channels's channel card #}
109 {{ macros.typed_card(card) if not (card.type == 'CHANNEL' and card.content.channel_id == channel_id) }}
110 {% endfor %}
111 {{ macros.dummycard() }}
112 </div>
113 <hr></details>
114 {% endblock %}
Imprint / Impressum