diff --git a/static/app.js b/static/app.js
index 06290b7..2f8ae09 100644
--- a/static/app.js
+++ b/static/app.js
@@ -267,7 +267,7 @@ function renderContent(data) {
contentHTML += `
Gestern`;
}
if (data.breadcrumbs.length === 1 && data.toplist_enabled) {
- contentHTML += ` oft angehört`;
+ contentHTML += ` häufig angehört`;
}
data.directories.forEach(dir => {
diff --git a/static/audioplayer.css b/static/audioplayer.css
index 6ce06ab..bda613a 100644
--- a/static/audioplayer.css
+++ b/static/audioplayer.css
@@ -175,8 +175,8 @@
/* Minimize button */
.minimize-button {
position: absolute;
- top: 6px;
- right: 6px;
+ top: 2px;
+ right: 2px;
width: 18px;
height: 18px;
border-radius: 8px;
@@ -187,7 +187,6 @@
align-items: center;
justify-content: center;
cursor: pointer;
- transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
padding: 0;
}
diff --git a/static/audioplayer.js b/static/audioplayer.js
index 722d046..d13b3a1 100644
--- a/static/audioplayer.js
+++ b/static/audioplayer.js
@@ -24,6 +24,8 @@ class SimpleAudioPlayer {
this.rafId = null;
this.abortCtrl = null;
this._hasMetadata = false;
+ this._posInterval = null;
+ this._posIntervalMs = 1000;
// Pre-compute icons once
const fill = getComputedStyle(document.documentElement)
@@ -87,6 +89,21 @@ class SimpleAudioPlayer {
`;
}
+ _startPositionSync() {
+ if (this._posInterval) return;
+ this._posInterval = setInterval(() => {
+ if (!this.audio.paused) {
+ this._pushPositionState();
+ }
+ }, this._posIntervalMs);
+ }
+
+ _stopPositionSync() {
+ if (!this._posInterval) return;
+ clearInterval(this._posInterval);
+ this._posInterval = null;
+ }
+
_bindEvents() {
this.playBtn.addEventListener('click', () => this.togglePlay());
if (this.minBtn) {
@@ -95,6 +112,7 @@ class SimpleAudioPlayer {
this.audio.addEventListener('loadstart', () => {
this._hasMetadata = false;
+ this._stopPositionSync();
this.timeline.min = 0;
this.timeline.max = 0;
this.timeline.value = 0;
@@ -114,6 +132,7 @@ class SimpleAudioPlayer {
this.audio.addEventListener('play', () => {
this._updatePlayState();
this._pushPositionState(true);
+ this._startPositionSync();
});
this.audio.addEventListener('playing', () => this._pushPositionState(true));
@@ -121,12 +140,14 @@ class SimpleAudioPlayer {
this.audio.addEventListener('pause', () => {
this._updatePlayState();
this._pushPositionState(true);
+ this._stopPositionSync();
});
this.audio.addEventListener('ratechange', () => this._pushPositionState(true));
this.audio.addEventListener('ended', () => {
this.playBtn.innerHTML = this.icons.play;
this._pushPositionState(true);
+ this._stopPositionSync();
if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';
});
@@ -134,7 +155,15 @@ class SimpleAudioPlayer {
this.audio.addEventListener('timeupdate', () => this.updateTimeline());
// Keep position in sync when page visibility changes
- document.addEventListener('visibilitychange', () => this._pushPositionState(true));
+ document.addEventListener('visibilitychange', () => {
+ this._pushPositionState(true);
+ if (document.visibilityState === 'visible' && !this.audio.paused) {
+ this._startPositionSync();
+ }
+ });
+
+ window.addEventListener('pageshow', () => this._pushPositionState(true));
+ window.addEventListener('focus', () => this._pushPositionState(true));
// Unified seek input
this.timeline.addEventListener('input', () => {
diff --git a/templates/permission.html b/templates/permission.html
index e423554..a2bf860 100644
--- a/templates/permission.html
+++ b/templates/permission.html
@@ -7,6 +7,6 @@
{# page content #}
{% block content %}
-
Du hast keine gültige Freigaben.
Bitte über einen Freigabelink oder QR-Code freischalten.
+
Du hast keine gültige Freigabe.
Bitte über einen Freigabelink oder QR-Code freischalten.
{% endblock %}