feat(player): add the song duration and display it properly
Parent
5d04971013
révision
9110b55710
|
@ -25,7 +25,7 @@
|
|||
<div class="player-progress" unicorn:ignore>
|
||||
<input aria-label="Seek" aria-valuemax="0" aria-valuemin="0" aria-valuenow="0" autocomplete="off" class="player-progress__range" data-player-target="progressSlider" max="100" min="0" role="slider" step="0.01" type="range" value="0">
|
||||
</div>
|
||||
<time class="player-time" data-player-target="duration" unicorn:ignore>--:--</time>
|
||||
<time class="player-time" data-player-target="duration" unicorn:ignore>
|
||||
</div>
|
||||
<div class="player__container player__container--current">
|
||||
<div class="song-title">
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from django.test.html import parse_html
|
||||
|
@ -5,7 +6,7 @@ from django.test.html import parse_html
|
|||
import pytest
|
||||
from wagtail_factories import ImageFactory
|
||||
|
||||
from wagtail_webradio.components.player import PlayerView, Playlist
|
||||
from wagtail_webradio.components.player import PlayerView, Playlist, Song
|
||||
|
||||
from .factories import PodcastFactory
|
||||
from .utils import prettify_html
|
||||
|
@ -19,6 +20,22 @@ def player():
|
|||
return component
|
||||
|
||||
|
||||
class TestSong:
|
||||
@pytest.mark.parametrize(
|
||||
'duration, result',
|
||||
[
|
||||
(None, '--:--'),
|
||||
(timedelta(), '--:--'),
|
||||
(timedelta(seconds=2), '00:02'),
|
||||
(timedelta(minutes=3), '03:00'),
|
||||
(timedelta(minutes=12, seconds=10), '12:10'),
|
||||
(timedelta(hours=1, seconds=10), '01:00:10'),
|
||||
],
|
||||
)
|
||||
def test_duration_str(self, duration, result):
|
||||
assert Song('t', 's', 'u', duration=duration).duration_str == result
|
||||
|
||||
|
||||
class TestPlaylist:
|
||||
def test_iter_items(self):
|
||||
song = {
|
||||
|
@ -158,6 +175,7 @@ class TestPlayer:
|
|||
title="The podcast",
|
||||
radio_show__title="The show",
|
||||
sound_url='https://example.org',
|
||||
duration=timedelta(minutes=3, seconds=10),
|
||||
)
|
||||
|
||||
player.add_podcast(podcast.pk)
|
||||
|
@ -166,6 +184,7 @@ class TestPlayer:
|
|||
assert song.title == "The podcast"
|
||||
assert song.subtitle == "The show"
|
||||
assert song.url == 'https://example.org'
|
||||
assert song.duration_str == '03:10'
|
||||
assert song.download_url == 'https://example.org'
|
||||
assert song.thumbnail_url == ''
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Optional, Union
|
||||
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from django_unicorn.components import UnicornView
|
||||
|
||||
from ..models import Podcast
|
||||
|
@ -13,9 +16,24 @@ class Song:
|
|||
url: str
|
||||
title: str
|
||||
subtitle: str
|
||||
duration: timedelta = None
|
||||
download_url: str = ''
|
||||
thumbnail_url: str = ''
|
||||
|
||||
@cached_property
|
||||
def duration_str(self):
|
||||
if not self.duration:
|
||||
return '--:--'
|
||||
result = []
|
||||
seconds = self.duration.total_seconds()
|
||||
if seconds >= 3600:
|
||||
hours, seconds = divmod(seconds, 3600)
|
||||
result.append('{:02n}'.format(hours))
|
||||
minutes, seconds = divmod(seconds, 60)
|
||||
result.append('{:02n}'.format(minutes))
|
||||
result.append('{:02n}'.format(seconds))
|
||||
return ':'.join(result)
|
||||
|
||||
|
||||
class Playlist(Sequence):
|
||||
def __init__(self):
|
||||
|
@ -256,6 +274,7 @@ class PlayerView(UnicornView):
|
|||
url=podcast.sound_url,
|
||||
title=podcast.title,
|
||||
subtitle=podcast.radio_show.title,
|
||||
duration=podcast.duration,
|
||||
download_url=podcast.sound_url,
|
||||
)
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<input type="range" class="player-progress__range" min="0" max="100" step="0.01" value="0" autocomplete="off" role="slider" aria-label="{% trans "Seek" %}" aria-valuenow="0" aria-valuemin="0" aria-valuemax="0" data-player-target="progressSlider">
|
||||
</div>
|
||||
|
||||
<time class="player-time" data-player-target="duration" unicorn:ignore>--:--</time>
|
||||
<time class="player-time" data-player-target="duration" unicorn:ignore>{{ current.duration_str }}</time>
|
||||
</div>
|
||||
<div class="player__container player__container--current">
|
||||
{% if current.thumbnail_url %}
|
||||
|
@ -75,6 +75,10 @@
|
|||
<p class="song__subtitle">{{ song.subtitle }}</p>
|
||||
</button>
|
||||
|
||||
{% if song.duration %}
|
||||
<time class="song__time">{{ song.duration_str }}</time>
|
||||
{% endif %}
|
||||
|
||||
<button type="button" class="btn btn-sm" aria-label="{% trans "Remove this song from the playlist" %}" unicorn:click="remove({{ id }})">
|
||||
{% block delete_icon %}
|
||||
<i class="fa fa-trash-o" aria-hidden="true"></i>
|
||||
|
|
Référencer dans un nouveau ticket