Add donation hint toast after 10 plays of same station
All checks were successful
Build and push Docker image / build (push) Successful in 11s
Test / test (push) Successful in 12s

This commit is contained in:
marwin 2026-03-16 20:57:07 +01:00
parent 945da36c95
commit 678912020c
3 changed files with 90 additions and 0 deletions

View file

@ -4,6 +4,7 @@ import urllib.parse
from datetime import datetime from datetime import datetime
import requests import requests
from django.db.models import Count
from django.conf import settings from django.conf import settings
from django.http import ( from django.http import (
HttpResponse, HttpResponse,
@ -30,11 +31,20 @@ def index(request):
history = [] history = []
if request.user.is_authenticated: if request.user.is_authenticated:
play_counts = {
sp['station_url']: sp['count']
for sp in StationPlay.objects
.filter(user=request.user)
.values('station_url')
.annotate(count=Count('id'))
}
saved_stations = list( saved_stations = list(
request.user.saved_stations.values( request.user.saved_stations.values(
'id', 'name', 'url', 'bitrate', 'country', 'tags', 'favicon_url', 'is_favorite' 'id', 'name', 'url', 'bitrate', 'country', 'tags', 'favicon_url', 'is_favorite'
) )
) )
for s in saved_stations:
s['play_count'] = play_counts.get(s['url'], 0)
history = list( history = list(
request.user.track_history.values( request.user.track_history.values(
'id', 'station_name', 'track', 'played_at', 'scrobbled' 'id', 'station_name', 'track', 'played_at', 'scrobbled'

View file

@ -911,3 +911,47 @@ body.dnd-mode .timer-display {
opacity: 0.5; opacity: 0.5;
} }
.btn-delete-history:hover { opacity: 1; color: #e55; } .btn-delete-history:hover { opacity: 1; color: #e55; }
#donation-hint {
position: fixed;
bottom: 24px;
right: 24px;
background: var(--surface, #1e1e2e);
border: 1px solid var(--border, #333);
border-radius: 8px;
padding: 12px 16px;
display: flex;
align-items: center;
gap: 12px;
font-size: 0.85rem;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
z-index: 999;
animation: hint-in 0.3s ease;
max-width: 320px;
}
#donation-hint.hiding {
animation: hint-out 0.4s ease forwards;
}
#donation-hint button {
background: none;
border: none;
cursor: pointer;
color: var(--muted, #888);
font-size: 0.8rem;
padding: 0;
flex-shrink: 0;
}
#donation-hint button:hover { color: var(--fg, #fff); }
@keyframes hint-in {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes hint-out {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(12px); }
}

View file

@ -71,6 +71,7 @@ function playStation(url, name, stationId) {
startMetadataSSE(url); startMetadataSSE(url);
startPlaySession(name, url); startPlaySession(name, url);
maybeShowDonationHint(url, name);
} }
function stopPlayback(clearStation = true) { function stopPlayback(clearStation = true) {
@ -829,6 +830,41 @@ function initCuratedLists() {
}); });
} }
// ---------------------------------------------------------------------------
// Donation hint
// ---------------------------------------------------------------------------
const DONATION_HINT_THRESHOLD = 10;
const DONATION_HINT_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
function maybeShowDonationHint(stationUrl, stationName) {
const station = INITIAL_SAVED.find(s => s.url === stationUrl);
if (!station || station.play_count < DONATION_HINT_THRESHOLD) return;
const key = `diora_donation_hint_${stationUrl}`;
const last = parseInt(localStorage.getItem(key) || '0', 10);
if (Date.now() - last < DONATION_HINT_COOLDOWN_MS) return;
const existing = document.getElementById('donation-hint');
if (existing) existing.remove();
const el = document.createElement('div');
el.id = 'donation-hint';
el.innerHTML = `
<span>You listen to <strong>${escapeHtml(stationName)}</strong> a lot consider supporting them </span>
<button onclick="dismissDonationHint('${escapeAttr(stationUrl)}')" title="Dismiss"></button>
`;
document.body.appendChild(el);
setTimeout(() => dismissDonationHint(stationUrl), 12000);
}
function dismissDonationHint(stationUrl) {
localStorage.setItem(`diora_donation_hint_${stationUrl}`, Date.now());
const el = document.getElementById('donation-hint');
if (el) { el.classList.add('hiding'); setTimeout(() => el.remove(), 400); }
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Station notes // Station notes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------