Skip to main content

max / makenotwork

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