diff --git a/static/audioplayer.js b/static/audioplayer.js
index dc3f2d4..c0f25b8 100644
--- a/static/audioplayer.js
+++ b/static/audioplayer.js
@@ -88,7 +88,7 @@ class SimpleAudioPlayer {
this.audio.currentTime = this.timeline.value;
// immediate Android sync
- if (navigator.mediaSession?.setPositionState) {
+ if (navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
navigator.mediaSession.setPositionState({
duration: this.audio.duration,
playbackRate: this.audio.playbackRate,
@@ -129,7 +129,7 @@ class SimpleAudioPlayer {
this.timeInfo.textContent =
`${this._formatTime(this.audio.currentTime)} / ${this._formatTime(this.audio.duration)}`;
// 4) Push to Android widget
- if (navigator.mediaSession?.setPositionState) {
+ if (navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
navigator.mediaSession.setPositionState({
duration: this.audio.duration,
playbackRate: this.audio.playbackRate,
@@ -138,6 +138,26 @@ class SimpleAudioPlayer {
}
}
+ async fileDownload() {
+ const src = this.audio.currentSrc || this.audio.src;
+ if (!src) return;
+
+ // Build the URL with your download flag + cache‑buster
+ const downloadUrl = new URL(src, window.location.href);
+ downloadUrl.searchParams.set('download', 'true');
+ downloadUrl.searchParams.set('_', Date.now());
+
+ // Create a “real” link to that URL and click it
+ const a = document.createElement('a');
+ a.href = downloadUrl.toString();
+ a.download = ''; // tell Safari “this is a download”
+ a.target = '_blank'; // force a real navigation on iOS
+ // NOTE: do NOT set a.download here – we want the server's Content-Disposition to drive it
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ }
+
async loadTrack(relUrl) {
this.audio.pause();
this.container.style.display = 'block';
@@ -159,9 +179,9 @@ class SimpleAudioPlayer {
// Full breadcrumb
const parts = relUrl.split('/');
const file = parts.pop();
- const folderPath = parts.join(' › ');
+ const folderPath = parts.join(' › ').replace('Gottesdienste S','S'); // Special case
this.nowInfo.innerHTML =
- `${folderPath} › ${file.replace(/\.[^/.]+$/, '')}`;
+ `${folderPath}
${file.replace(/\.[^/.]+$/, '')}`;
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
@@ -222,7 +242,7 @@ class SimpleAudioPlayer {
// Heartbeat for widget
this._posInterval = setInterval(() => {
- if (!this.audio.paused && navigator.mediaSession.setPositionState) {
+ if (!this.audio.paused && navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
navigator.mediaSession.setPositionState({
duration: this.audio.duration,
playbackRate: this.audio.playbackRate,
diff --git a/templates/app.html b/templates/app.html
index cc8fb77..5a582a6 100644
--- a/templates/app.html
+++ b/templates/app.html
@@ -204,7 +204,7 @@