diff --git a/index.html b/index.html
index 568f5b2..c836bea 100644
--- a/index.html
+++ b/index.html
@@ -637,11 +637,16 @@
-
-
-
+
+
+
Audiobookshelf Status
+
Nicht verbunden
+
+
-
diff --git a/src/abs.js b/src/abs.js
index bef7f40..62fbaa4 100644
--- a/src/abs.js
+++ b/src/abs.js
@@ -659,12 +659,42 @@ function _showAbsNavItem(show) {
if (bnav) bnav.style.display = show ? '' : 'none';
}
+function _setAbsStatusRow(state, msg) {
+ // state: 'connected' | 'error' | 'none'
+ const statusEl = document.getElementById('abs-s-status');
+ const dotEl = document.getElementById('abs-s-dot');
+ const btnEl = document.getElementById('abs-s-connect-btn');
+ if (statusEl) statusEl.textContent = msg || 'Nicht verbunden';
+ if (dotEl) {
+ dotEl.style.display = state === 'none' ? 'none' : 'block';
+ dotEl.className = 'status-dot' + (state === 'connected' ? ' ok' : state === 'error' ? ' err' : '');
+ }
+ if (btnEl) {
+ btnEl.disabled = false;
+ if (state === 'connected') {
+ btnEl.textContent = 'Trennen';
+ btnEl.style.color = 'var(--danger)';
+ btnEl.style.borderColor = 'rgba(224,85,85,0.3)';
+ } else {
+ btnEl.textContent = 'Verbinden';
+ btnEl.style.color = '';
+ btnEl.style.borderColor = '';
+ }
+ }
+}
+
export function absOpenSettings() {
const urlEl = document.getElementById('abs-s-url');
if (urlEl) urlEl.value = S.abs.url || '';
- // Never pre-fill the API key field for security — just show connection status
- const statusEl = document.getElementById('abs-s-status');
- if (statusEl) statusEl.textContent = S.abs.token ? '✅ Verbunden' : '';
+ if (S.abs.token) {
+ _setAbsStatusRow('connected', 'Verbunden · ' + (S.abs.url || ''));
+ } else {
+ _setAbsStatusRow('none', 'Nicht verbunden');
+ }
+}
+
+export function absToggleConnection() {
+ if (S.abs.token) absDisconnect(); else absConnectSettings();
}
export async function absConnectSettings() {
@@ -681,13 +711,11 @@ export async function absConnectSettings() {
_renderLibPicker(libs);
_showAbsNavItem(true);
toast('✅ Audiobookshelf verbunden');
- const statusEl = document.getElementById('abs-s-status');
- if (statusEl) statusEl.textContent = '✅ Verbunden';
+ _setAbsStatusRow('connected', 'Verbunden · ' + url);
} catch (e) {
S.abs.token = null;
toast(`❌ ABS Verbindung fehlgeschlagen: ${e.message}`);
- } finally {
- if (btn) { btn.disabled = false; btn.textContent = 'Verbinden'; }
+ _setAbsStatusRow('error', 'Fehler: ' + e.message);
}
}
@@ -722,6 +750,5 @@ export function absDisconnect() {
localStorage.removeItem('ns_abs');
_showAbsNavItem(false);
toast('Audiobookshelf getrennt');
- const statusEl = document.getElementById('abs-s-status');
- if (statusEl) statusEl.textContent = '';
+ _setAbsStatusRow('none', 'Nicht verbunden');
}
diff --git a/src/main.js b/src/main.js
index 1500264..20e816b 100644
--- a/src/main.js
+++ b/src/main.js
@@ -23,7 +23,7 @@ import { loadSpotifyImporter, resolveSpotifyLink, clearSpotifyPreview, spotifyDl
import { resolveYouTubeLink, executeYouTubeDownload } from './youtube.js';
import { loadSoundCloudImporter, resolveSoundCloudLink, clearSoundCloudPreview, scDlAll, scDlSingle, scDlTrack } from './soundcloud.js';
import {
- absInitFromStorage, absOpenSettings, absConnectSettings, absSetLibrary, absDisconnect, absVerifyApiKey,
+ absInitFromStorage, absOpenSettings, absConnectSettings, absSetLibrary, absDisconnect, absVerifyApiKey, absToggleConnection,
absPlayItem, absTogglePlay, absSeek, absSkipSecs, absNextChapter, absPrevChapter,
absSetSpeed, absSleepIn, absOpenPlayer, absClosePlayer, absToggleChapters,
absToggleSpeedPicker, absToggleSleepPicker, absSeekToChapter, absProgDown, absProgMove,
@@ -334,7 +334,7 @@ Object.assign(window, {
absSetSpeed, absSleepIn, absOpenPlayer, absClosePlayer, absToggleChapters,
absToggleSpeedPicker, absToggleSleepPicker, absSeekToChapter,
absProgDown, absProgMove, absProgUp,
- absOpenBook, absPlayChapter, absConnectSettings, absSetLibrary, absDisconnect, absToggleChapterTrack,
+ absOpenBook, absPlayChapter, absConnectSettings, absSetLibrary, absDisconnect, absToggleConnection, absToggleChapterTrack,
absOnSearch: (val) => {
clearTimeout(window._absSearchTimer);
window._absSearchTimer = setTimeout(() => {