Add donation hint toast after 10 plays of same station
This commit is contained in:
parent
945da36c95
commit
678912020c
3 changed files with 90 additions and 0 deletions
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue