From 8b6a4a3b8d18a86c622290cc81ba7697b2bf18b4 Mon Sep 17 00:00:00 2001 From: Dan Jacob Date: Sun, 12 Jan 2025 15:34:02 +0200 Subject: [PATCH] feat: show exact time remaining for episode --- radiofeed/episodes/models.py | 5 +++++ radiofeed/episodes/tests/test_models.py | 16 ++++++++++++++++ radiofeed/templatetags.py | 12 ------------ radiofeed/tests/test_templatetags.py | 22 +--------------------- templates/episodes/detail.html | 6 +++--- 5 files changed, 25 insertions(+), 36 deletions(-) diff --git a/radiofeed/episodes/models.py b/radiofeed/episodes/models.py index f4c030f4e..6bbe0a438 100644 --- a/radiofeed/episodes/models.py +++ b/radiofeed/episodes/models.py @@ -267,3 +267,8 @@ def __str__(self) -> str: self.listened.isoformat(), ] ) + + @cached_property + def time_remaining(self) -> int: + """Returns the time remaining in the episode in seconds.""" + return max(self.episode.duration_in_seconds - self.current_time, 0) diff --git a/radiofeed/episodes/tests/test_models.py b/radiofeed/episodes/tests/test_models.py index 5c51000c8..67e3a118c 100644 --- a/radiofeed/episodes/tests/test_models.py +++ b/radiofeed/episodes/tests/test_models.py @@ -193,3 +193,19 @@ def test_str(self): listened=datetime.datetime(year=2024, month=9, day=10), ) assert str(audio_log) == "user 1 | episode 2 | 2024-09-10T00:00:00" + + @pytest.mark.django_db + def test_time_remaining(self): + audio_log = AudioLogFactory( + episode__duration="1:00:00", + current_time=60 * 10, + ) + assert audio_log.time_remaining == 50 * 60 + + @pytest.mark.django_db + def test_time_remaining_negative(self): + audio_log = AudioLogFactory( + episode__duration="1:00:00", + current_time=60 * 70, + ) + assert audio_log.time_remaining == 0 diff --git a/radiofeed/templatetags.py b/radiofeed/templatetags.py index b2da45098..4894eb19b 100644 --- a/radiofeed/templatetags.py +++ b/radiofeed/templatetags.py @@ -87,15 +87,3 @@ def format_duration(total_seconds: int | None) -> str: rv.append(f"{total_minutes} minute{pluralize(total_minutes)}") return " ".join(rv) - - -@register.filter -def percentage(value: float, total: float) -> int: - """Returns % value. - - Example: - {{ value|percentage:total }}% done - """ - if 0 in (value, total): - return 0 - return min(math.ceil((value / total) * 100), 100) diff --git a/radiofeed/tests/test_templatetags.py b/radiofeed/tests/test_templatetags.py index f752b4304..964dc09a4 100644 --- a/radiofeed/tests/test_templatetags.py +++ b/radiofeed/tests/test_templatetags.py @@ -1,11 +1,7 @@ import pytest from django.contrib.sites.models import Site -from radiofeed.templatetags import ( - absolute_uri, - format_duration, - percentage, -) +from radiofeed.templatetags import absolute_uri, format_duration @pytest.fixture @@ -23,22 +19,6 @@ def auth_req(req, user): return req -class TestPercentage: - @pytest.mark.parametrize( - ("value", "total", "expected"), - [ - pytest.param(0, 0, 0, id="all zero"), - pytest.param(50, 0, 0, id="total zero"), - pytest.param(0, 50, 0, id="value zero"), - pytest.param(50, 100, 50, id="50%"), - pytest.param(150, 100, 100, id="150%"), - pytest.param(100, 100, 100, id="100%"), - ], - ) - def test_percentage(self, value, total, expected): - assert percentage(value, total) == expected - - class TestFormatDuration: @pytest.mark.parametrize( ("duration", "expected"), diff --git a/templates/episodes/detail.html b/templates/episodes/detail.html index 42aba5e72..9609a4aa9 100644 --- a/templates/episodes/detail.html +++ b/templates/episodes/detail.html @@ -180,9 +180,9 @@

Listened {{ audio_log.listened|date:"DATE_FORMAT" }} - {% with percent_complete=audio_log.current_time|percentage:episode.duration_in_seconds %} - {% if percent_complete > 0 and percent_complete < 100 %} - {{ percent_complete }}% Complete + {% with time_remaining=audio_log.time_remaining|format_duration %} + {% if audio_log.current_time and time_remaining %} + {{ time_remaining }} left {% endif %} {% endwith %}