fix: CROS fix, Mini Bar fix switches Audiobook and Music Player, Chapter Track mode added, Delted Playlist mode from Audiobooks
This commit is contained in:
1 parent
8f126562e7
commit
eb4d6fcbf9
5 files changed
+61
-55
No files matched your search
@@ -23,7 +23,7 @@ const { downloadTrack, downloadAlbumTracks } = require('./lib/downloader');
|
||||
const app = express();
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PATCH,DELETE,OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization,X-ABS-URL,X-ABS-Token');
|
||||
res.setHeader('Access-Control-Allow-Private-Network', 'true');
|
||||
if (req.method === 'OPTIONS') { res.sendStatus(204); return; }
|
||||
|
||||
+16
-8
@@ -435,16 +435,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ABS MINI BAR -->
|
||||
<div id="abs-mini-bar" class="abs-mini-bar" onclick="absOpenPlayer()">
|
||||
<div id="abs-mini-cover" class="abs-mini-cover">📚</div>
|
||||
<div class="abs-mini-info">
|
||||
<!-- ABS MINI BAR (overlays the music player bar when an audiobook is active) -->
|
||||
<div id="abs-mini-bar" class="abs-mini-bar">
|
||||
<div class="abs-mini-prog-strip"><div id="abs-mini-prog-fill" class="abs-mini-prog-fill"></div></div>
|
||||
<div id="abs-mini-cover" class="abs-mini-cover" onclick="absOpenPlayer()">📚</div>
|
||||
<div class="abs-mini-info" onclick="absOpenPlayer()">
|
||||
<div id="abs-mini-title" class="abs-mini-title">—</div>
|
||||
<div id="abs-mini-chapter" class="abs-mini-chapter"></div>
|
||||
</div>
|
||||
<button class="abs-mini-play" id="abs-mini-play" onclick="event.stopPropagation();absTogglePlay()">
|
||||
<button class="abs-mini-play" id="abs-mini-play" onclick="absTogglePlay()">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
|
||||
</button>
|
||||
<button class="abs-mini-open" onclick="absOpenPlayer()" title="Öffnen">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- PREVIEW BAR (iTunes 30s) -->
|
||||
@@ -598,9 +602,7 @@
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
</button>
|
||||
<span class="abs-player-label">Hörbuch</span>
|
||||
<button class="abs-hbtn" id="abs-playlist-btn" onclick="absTogglePlaylistMode()" title="Kapitelliste fixieren">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="3" cy="6" r="1.2" fill="currentColor" stroke="none"/><circle cx="3" cy="12" r="1.2" fill="currentColor" stroke="none"/><circle cx="3" cy="18" r="1.2" fill="currentColor" stroke="none"/></svg>
|
||||
</button>
|
||||
<div style="width:36px"></div>
|
||||
</div>
|
||||
|
||||
<!-- Cover -->
|
||||
@@ -702,6 +704,12 @@
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
|
||||
Kapitel
|
||||
</button>
|
||||
|
||||
<!-- Chapter track mode -->
|
||||
<button class="abs-extra-btn" id="abs-chtrack-btn" onclick="absToggleChapterTrack()" title="Kapitel-Track: Fortschritt nur im aktuellen Kapitel anzeigen">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12"/><line x1="12" y1="12" x2="15" y2="15"/><line x1="3" y1="12" x2="6" y2="12" stroke-width="2.5"/></svg>
|
||||
Kap.Track
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Chapter list -->
|
||||
|
||||
+31
-32
@@ -185,10 +185,6 @@ function _updateChapter() {
|
||||
ap.chapterIdx = idx;
|
||||
_renderChapterName();
|
||||
_renderChapterList();
|
||||
if (_playlistMode) {
|
||||
const cl = document.getElementById('abs-chapter-list');
|
||||
setTimeout(() => cl?.querySelector('.abs-ch-item.active')?.scrollIntoView({ block: 'nearest', behavior: 'smooth' }), 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +340,6 @@ export function absClosePlayer() {
|
||||
}
|
||||
|
||||
export function absToggleChapters() {
|
||||
if (_playlistMode) return;
|
||||
document.getElementById('abs-chapter-list')?.classList.toggle('open');
|
||||
_renderChapterList();
|
||||
}
|
||||
@@ -364,28 +359,22 @@ export function absSeekToChapter(idx) {
|
||||
if (ch) absSeek(ch.start);
|
||||
}
|
||||
|
||||
// ─── PLAYLIST MODE ───
|
||||
let _playlistMode = localStorage.getItem('ns_abs_pl_mode') === '1';
|
||||
// ─── CHAPTER TRACK MODE ───
|
||||
let _chapterTrackMode = localStorage.getItem('ns_abs_chtrack') === '1';
|
||||
|
||||
export function absTogglePlaylistMode() {
|
||||
_playlistMode = !_playlistMode;
|
||||
localStorage.setItem('ns_abs_pl_mode', _playlistMode ? '1' : '0');
|
||||
_applyPlaylistMode();
|
||||
export function absToggleChapterTrack() {
|
||||
_chapterTrackMode = !_chapterTrackMode;
|
||||
localStorage.setItem('ns_abs_chtrack', _chapterTrackMode ? '1' : '0');
|
||||
document.getElementById('abs-chtrack-btn')?.classList.toggle('active', _chapterTrackMode);
|
||||
_renderProgress();
|
||||
}
|
||||
|
||||
function _applyPlaylistMode() {
|
||||
const overlay = document.getElementById('abs-player');
|
||||
overlay?.classList.toggle('playlist-mode', _playlistMode);
|
||||
document.getElementById('abs-playlist-btn')?.classList.toggle('active', _playlistMode);
|
||||
const cl = document.getElementById('abs-chapter-list');
|
||||
if (!cl) return;
|
||||
if (_playlistMode) {
|
||||
cl.classList.add('open');
|
||||
_renderChapterList();
|
||||
setTimeout(() => cl.querySelector('.abs-ch-item.active')?.scrollIntoView({ block: 'nearest', behavior: 'smooth' }), 50);
|
||||
} else {
|
||||
cl.classList.remove('open');
|
||||
}
|
||||
function _chapterWindow() {
|
||||
const ap = S.absPlayer;
|
||||
if (!_chapterTrackMode || ap.chapterIdx < 0 || !ap.chapters.length) return null;
|
||||
const ch = ap.chapters[ap.chapterIdx];
|
||||
const nextCh = ap.chapters[ap.chapterIdx + 1];
|
||||
return { start: ch.start ?? 0, end: nextCh?.start ?? ap.duration };
|
||||
}
|
||||
|
||||
// ─── PROGRESS SCRUB ───
|
||||
@@ -397,8 +386,9 @@ function _scrub(e) {
|
||||
const bar = document.getElementById('abs-prog-bar');
|
||||
if (!bar) return;
|
||||
const rect = bar.getBoundingClientRect();
|
||||
const x = (e.touches?.[0]?.clientX ?? e.clientX) - rect.left;
|
||||
absSeek((Math.max(0, Math.min(1, x / rect.width))) * S.absPlayer.duration);
|
||||
const pct = Math.max(0, Math.min(1, ((e.touches?.[0]?.clientX ?? e.clientX) - rect.left) / rect.width));
|
||||
const win = _chapterWindow();
|
||||
absSeek(win ? win.start + pct * (win.end - win.start) : pct * S.absPlayer.duration);
|
||||
}
|
||||
|
||||
// ─── RENDER HELPERS ───
|
||||
@@ -456,20 +446,29 @@ function _renderPlayer() {
|
||||
_renderChapterName();
|
||||
_renderSleepBtn();
|
||||
_renderMiniBar();
|
||||
_applyPlaylistMode();
|
||||
document.getElementById('abs-chtrack-btn')?.classList.toggle('active', _chapterTrackMode);
|
||||
}
|
||||
|
||||
function _renderProgress() {
|
||||
const ap = S.absPlayer;
|
||||
const pct = ap.duration > 0 ? (ap.currentTime / ap.duration) * 100 : 0;
|
||||
const win = _chapterWindow();
|
||||
const dispCur = win ? ap.currentTime - win.start : ap.currentTime;
|
||||
const dispDur = win ? win.end - win.start : ap.duration;
|
||||
const pct = dispDur > 0 ? Math.min(100, (dispCur / dispDur) * 100) : 0;
|
||||
|
||||
const fill = document.getElementById('abs-prog-fill');
|
||||
const thumb = document.getElementById('abs-prog-thumb');
|
||||
if (fill) fill.style.width = `${Math.min(100, pct)}%`;
|
||||
if (thumb) thumb.style.left = `${Math.min(100, pct)}%`;
|
||||
if (fill) fill.style.width = `${pct}%`;
|
||||
if (thumb) thumb.style.left = `${pct}%`;
|
||||
const cur = document.getElementById('abs-time-cur');
|
||||
const rem = document.getElementById('abs-time-rem');
|
||||
if (cur) cur.textContent = _fmt(ap.currentTime);
|
||||
if (rem) rem.textContent = `-${_fmt(ap.duration - ap.currentTime)}`;
|
||||
if (cur) cur.textContent = _fmt(dispCur);
|
||||
if (rem) rem.textContent = `-${_fmt(dispDur - dispCur)}`;
|
||||
|
||||
// mini bar strip always shows full-book progress
|
||||
const miniPct = ap.duration > 0 ? Math.min(100, (ap.currentTime / ap.duration) * 100) : 0;
|
||||
const miniFill = document.getElementById('abs-mini-prog-fill');
|
||||
if (miniFill) miniFill.style.width = `${miniPct}%`;
|
||||
}
|
||||
|
||||
function _renderControls() {
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import {
|
||||
absSetSpeed, absSleepIn, absOpenPlayer, absClosePlayer, absToggleChapters,
|
||||
absToggleSpeedPicker, absToggleSleepPicker, absSeekToChapter, absProgDown, absProgMove,
|
||||
absProgUp, loadAbsBooks, absOpenBook, loadAbsBookDetail, absPlayChapter,
|
||||
absLoadSettingsLibraries, absTogglePlaylistMode, absInterrupt,
|
||||
absLoadSettingsLibraries, absToggleChapterTrack, absInterrupt,
|
||||
} from './abs.js';
|
||||
import {
|
||||
openNowPlaying, closeNowPlaying, switchNpTab, npGoArtist, npGoAlbum,
|
||||
@@ -271,7 +271,7 @@ Object.assign(window, {
|
||||
absSetSpeed, absSleepIn, absOpenPlayer, absClosePlayer, absToggleChapters,
|
||||
absToggleSpeedPicker, absToggleSleepPicker, absSeekToChapter,
|
||||
absProgDown, absProgMove, absProgUp,
|
||||
absOpenBook, absPlayChapter, absConnectSettings, absSetLibrary, absDisconnect, absTogglePlaylistMode,
|
||||
absOpenBook, absPlayChapter, absConnectSettings, absSetLibrary, absDisconnect, absToggleChapterTrack,
|
||||
absOnSearch: (val) => {
|
||||
clearTimeout(window._absSearchTimer);
|
||||
window._absSearchTimer = setTimeout(() => {
|
||||
|
||||
+11
-12
@@ -952,18 +952,17 @@ nav{flex:1;overflow-y:auto;padding:4px 10px}
|
||||
.abs-cover-wrap{width:min(240px,calc(100vw - 48px))}
|
||||
}
|
||||
|
||||
/* ── ABS MINI BAR ── */
|
||||
.abs-mini-bar{position:fixed;bottom:var(--player-h);left:0;right:0;background:rgba(10,10,28,.96);backdrop-filter:blur(16px);border-top:1px solid rgba(130,80,255,.25);padding:9px 16px;display:flex;align-items:center;gap:12px;z-index:99;transform:translateY(100%);transition:transform .3s;cursor:pointer}
|
||||
/* ── ABS MINI BAR (overlays the bottom player bar) ── */
|
||||
.abs-mini-bar{position:fixed;bottom:0;left:0;right:0;height:var(--player-h);background:rgba(8,8,20,.96);backdrop-filter:blur(28px);border-top:1px solid var(--border2);padding:0 16px;display:flex;align-items:center;gap:12px;z-index:101;transform:translateY(100%);transition:transform .3s}
|
||||
.abs-mini-bar.visible{transform:translateY(0)}
|
||||
.abs-mini-cover{width:40px;height:40px;border-radius:7px;background:var(--surface2);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0;overflow:hidden}
|
||||
.abs-mini-info{flex:1;min-width:0}
|
||||
.abs-mini-prog-strip{position:absolute;top:0;left:0;right:0;height:3px;background:var(--border2)}
|
||||
.abs-mini-prog-fill{height:100%;background:var(--accent);transition:width .5s linear;width:0}
|
||||
.abs-mini-cover{width:46px;height:46px;border-radius:8px;background:var(--surface2);display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0;overflow:hidden;cursor:pointer}
|
||||
.abs-mini-info{flex:1;min-width:0;cursor:pointer}
|
||||
.abs-mini-title{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.abs-mini-chapter{font-size:11px;color:var(--text2);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.abs-mini-play{background:none;border:none;color:var(--text);cursor:pointer;padding:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
@media(max-width:768px){.abs-mini-bar{bottom:calc(var(--player-h) + 80px + env(safe-area-inset-bottom))}}
|
||||
|
||||
/* ── ABS PLAYLIST MODE ── */
|
||||
.abs-mini-chapter{font-size:11px;color:var(--text2);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.abs-mini-play{background:none;border:none;color:var(--text);cursor:pointer;padding:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
.abs-mini-open{background:none;border:none;color:var(--text2);cursor:pointer;padding:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
.abs-mini-open:hover{color:var(--text)}
|
||||
.abs-hbtn.active{color:var(--accent)}
|
||||
.abs-player-overlay.playlist-mode .abs-cover-area{flex:0 0 auto;padding:4px 40px}
|
||||
.abs-player-overlay.playlist-mode .abs-cover-wrap{width:min(140px,calc(100vw - 80px))}
|
||||
.abs-player-overlay.playlist-mode .abs-chapter-list.open{flex:1;max-height:none;overflow-y:auto}
|
||||
@media(max-width:768px){.abs-mini-bar{bottom:80px;height:var(--player-h)}}
|
||||
Reference in new issue
Block a user