Skip to main content

max / makenotwork

6.6 KB · 165 lines History Blame Raw
1 {% extends "base.html" %}
2
3 {% block title %}{{ item.title }} - Library - Makenotwork{% endblock %}
4
5 {% block head %}
6 <meta name="robots" content="noindex">
7 <link rel="stylesheet" href="/static/media-player.css">
8 {% endblock %}
9
10 {% block content %}
11 {% include "partials/site_header.html" %}
12
13 <article class="media-container">
14 <p class="library-back">
15 <a href="/i/{{ item.id }}">&larr; Store page</a> &middot;
16 <a href="/library">Your library</a>
17 </p>
18
19 <header class="author-header">
20 <div class="author-avatar">{{ creator_avatar_initials }}</div>
21 <div class="author-info">
22 <div class="author-name"><a href="/u/{{ creator_username }}">{% if let Some(name) = creator_display_name %}{{ name }}{% else %}{{ creator_username }}{% endif %}</a></div>
23 <div class="media-meta">{{ item.release_date }}{% match item.content %}{% when crate::types::ItemContent::Video with { duration, .. } %}{% if let Some(dur) = duration %} | {{ dur }}{% endif %}{% when _ %}{% endmatch %}</div>
24 </div>
25 </header>
26
27 <h1 class="media-title">{{ item.title }}</h1>
28
29 {% if let Some(project_title) = project_title %}
30 <p class="media-series">
31 <a href="/p/{{ project_slug }}">{{ project_title }}</a>
32 </p>
33 {% endif %}
34
35 <div class="video-display">
36 <video id="media-a" preload="metadata"
37 {% match item.content %}{% when crate::types::ItemContent::Video with { cover_url, .. } %}{% if let Some(url) = cover_url %}poster="{{ url }}"{% endif %}{% when _ %}{% endmatch %}>
38 {% if let Some(vurl) = video_url %}
39 <source src="{{ vurl }}">
40 {% endif %}
41 </video>
42 </div>
43
44 <div class="media-player">
45 <div class="player-controls">
46 <button class="play-button" id="play-btn" aria-label="Play">
47 <svg id="play-icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
48 <path d="M8 5v14l11-7z"/>
49 </svg>
50 <svg id="pause-icon" class="media-icon-hidden" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
51 <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
52 </svg>
53 </button>
54 <div class="progress-container">
55 <div class="progress-bar" id="progress-bar">
56 <div class="progress-fill" id="progress-fill"></div>
57 </div>
58 <div class="time-display">
59 <span id="current-time">0:00</span>
60 <span id="duration">0:00</span>
61 </div>
62 </div>
63 </div>
64
65 <div class="insertion-label" id="insertion-label"></div>
66 <button class="skip-insertion" id="skip-btn" type="button">Skip &#8250;</button>
67
68 <div class="player-secondary">
69 <div class="speed-control">
70 <span>Speed:</span>
71 <button class="speed-button" data-speed="0.5">0.5x</button>
72 <button class="speed-button is-selected" data-speed="1">1x</button>
73 <button class="speed-button" data-speed="1.5">1.5x</button>
74 <button class="speed-button" data-speed="2">2x</button>
75 </div>
76 <div class="volume-control">
77 <span class="volume-icon">
78 <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
79 <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>
80 </svg>
81 </span>
82 <input type="range" class="volume-slider" id="volume-slider" min="0" max="100" value="75" />
83 </div>
84 </div>
85 </div>
86
87 {% if !chapters.is_empty() %}
88 <div class="chapters">
89 <h3>Chapters</h3>
90 <ul class="chapter-list">
91 {% for chapter in chapters %}
92 <li class="chapter-item" data-time="{{ chapter.start_seconds }}">
93 <span class="chapter-title">{{ chapter.title }}</span>
94 <span class="chapter-time">{{ chapter.timestamp }}</span>
95 </li>
96 {% endfor %}
97 </ul>
98 </div>
99 {% endif %}
100
101 {% if !item.description.is_empty() %}
102 <div class="media-description">
103 <p>{{ item.description }}</p>
104 </div>
105 {% endif %}
106
107 {% if !versions.is_empty() %}
108 <section class="library-downloads">
109 <h3>Source files</h3>
110 {% for version in versions %}
111 {% if version.has_file %}
112 <div class="download-row">
113 <span class="download-version">v{{ version.number }}</span>
114 {% if let Some(label) = version.label %}
115 <span class="download-label">{{ label }}</span>
116 {% else %}
117 <span class="download-label download-label--empty">{% match version.file_name %}{% when Some with (name) %}{{ name }}{% when None %}Download{% endmatch %}</span>
118 {% endif %}
119 <span class="download-size">{{ version.size }}</span>
120 <button class="btn-secondary btn-download-compact"
121 onclick="downloadVersion('{{ version.id }}')">Download</button>
122 </div>
123 {% endif %}
124 {% endfor %}
125 </section>
126 {% endif %}
127 </article>
128
129 {% include "partials/discussion_section.html" %}
130
131 <footer class="media-player-footer">
132 {% if is_owner %}
133 <a href="/dashboard/item/{{ item.id }}">Edit</a> &middot;
134 {% endif %}
135 <a href="/i/{{ item.id }}">Store page</a> &middot;
136 <a href="/library">Your library</a>
137 </footer>
138 {% endblock %}
139
140 {% block scripts %}
141 <script id="media-player-data" type="application/json">
142 {
143 "segments": {{ segments_json|safe }},
144 "mediaType": "video",
145 "itemId": "{{ item.id }}"
146 }
147 </script>
148 <script src="/static/media-player.js"></script>
149 <script>
150 function downloadVersion(versionId) {
151 fetch('/api/versions/' + versionId + '/download')
152 .then(function(res) {
153 if (!res.ok) throw new Error('Failed to get download URL');
154 return res.json();
155 })
156 .then(function(data) {
157 window.location.href = data.download_url;
158 })
159 .catch(function(err) {
160 showToast(err.message || 'Download failed');
161 });
162 }
163 </script>
164 {% endblock %}
165