fix(ui/ux): keep the import search dialog inside the viewport
This commit is contained in:
+13
-9
@@ -962,20 +962,24 @@ async function runQuickSearch() {
|
|||||||
box.innerHTML = `<p class='muted'>${EMPTY_HINTS[item.media_type]}</p>`;
|
box.innerHTML = `<p class='muted'>${EMPTY_HINTS[item.media_type]}</p>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// one compact row per hit: cover, title + a single meta line, action right
|
||||||
box.innerHTML = results
|
box.innerHTML = results
|
||||||
.map(
|
.map((r, j) => {
|
||||||
(r, j) => `<div class="card">
|
const meta = [
|
||||||
|
r.authors,
|
||||||
|
r.narrator ? "🎙 " + r.narrator : "",
|
||||||
|
r.series ? `📚 ${r.series}${r.volume != null ? " #" + r.volume : ""}` : "",
|
||||||
|
r.year ?? "",
|
||||||
|
].filter(Boolean).map(esc).join(" · ");
|
||||||
|
return `<div class="card">
|
||||||
${r.cover_url ? `<img src="${esc(r.cover_url)}" alt="" loading="lazy">` : '<div class="nocover">?</div>'}
|
${r.cover_url ? `<img src="${esc(r.cover_url)}" alt="" loading="lazy">` : '<div class="nocover">?</div>'}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<strong>${esc(r.title)}</strong>
|
<strong>${esc(r.title)}</strong>
|
||||||
<span>${esc(r.authors)}</span>
|
<span class="muted">${meta}</span>
|
||||||
${r.narrator ? `<span class="muted">🎙 ${esc(r.narrator)}</span>` : ""}
|
|
||||||
${r.series && r.media_type ? `<span class="muted">📚 ${esc(r.series)}${r.volume != null ? " #" + r.volume : ""}</span>` : ""}
|
|
||||||
<span class="muted">${r.year ?? ""}</span>
|
|
||||||
<div class="row"><button data-pick="${j}">Anfragen & verbinden</button></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
<button data-pick="${j}" title="Anfrage anlegen und mit diesem Eintrag verbinden">Verbinden</button>
|
||||||
)
|
</div>`;
|
||||||
|
})
|
||||||
.join("");
|
.join("");
|
||||||
box.querySelectorAll("[data-pick]").forEach((btn) =>
|
box.querySelectorAll("[data-pick]").forEach((btn) =>
|
||||||
btn.addEventListener("click", () => pickQuickResult(results[btn.dataset.pick]))
|
btn.addEventListener("click", () => pickQuickResult(results[btn.dataset.pick]))
|
||||||
|
|||||||
+19
-14
@@ -202,21 +202,26 @@
|
|||||||
<label class="muted"
|
<label class="muted"
|
||||||
>Ziel-Library <select id="quick-library"></select
|
>Ziel-Library <select id="quick-library"></select
|
||||||
></label>
|
></label>
|
||||||
<div id="quick-open-requests"></div>
|
<div id="quick-scroll">
|
||||||
<div id="quick-results" class="cards"></div>
|
<div id="quick-open-requests"></div>
|
||||||
<details id="quick-manual">
|
<div id="quick-results" class="cards view-list"></div>
|
||||||
<summary>Nicht bei Audible? Manuell anlegen</summary>
|
</div>
|
||||||
<div class="bar wrap">
|
<div id="quick-foot">
|
||||||
<label>Titel <input id="quick-m-title" /></label>
|
<details id="quick-manual">
|
||||||
<label>Serie <input id="quick-m-series" placeholder="optional" /></label>
|
<summary>Nicht bei Audible? Manuell anlegen</summary>
|
||||||
<label>Folge/Band <input id="quick-m-volume" type="number" min="0" /></label>
|
<div class="quick-manual-fields">
|
||||||
|
<label>Titel <input id="quick-m-title" /></label>
|
||||||
|
<label>Serie <input id="quick-m-series" placeholder="optional" /></label>
|
||||||
|
<label class="narrow"
|
||||||
|
>Folge/Band <input id="quick-m-volume" type="number" min="0" /></label>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="quick-m-submit">Anlegen & verbinden</button>
|
||||||
|
</details>
|
||||||
|
<div class="row">
|
||||||
|
<button type="button" id="quick-close" class="secondary">
|
||||||
|
Schließen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="quick-m-submit">Anlegen & verbinden</button>
|
|
||||||
</details>
|
|
||||||
<div class="row">
|
|
||||||
<button type="button" id="quick-close" class="secondary">
|
|
||||||
Schließen
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+21
-1
@@ -105,7 +105,27 @@ dialog label { display: flex; flex-direction: column; gap: 0.2rem; margin: 0.5re
|
|||||||
.series-list input[type=checkbox] { flex: none; }
|
.series-list input[type=checkbox] { flex: none; }
|
||||||
.series-list .num { flex: none; min-width: 3.2em; color: var(--muted); font-variant-numeric: tabular-nums; }
|
.series-list .num { flex: none; min-width: 3.2em; color: var(--muted); font-variant-numeric: tabular-nums; }
|
||||||
.series-list .gap { padding: 0.35rem 0.6rem; color: var(--muted); font-size: 0.85rem; }
|
.series-list .gap { padding: 0.35rem 0.6rem; color: var(--muted); font-size: 0.85rem; }
|
||||||
#quick-results { display: flex; flex-direction: column; max-height: 50vh; overflow-y: auto; margin-top: 0.6rem; }
|
/* the dialog keeps head and foot in place; only the results scroll, so the
|
||||||
|
"manuell anlegen" panel stays reachable no matter how many hits came back */
|
||||||
|
#quick-dialog { display: flex; flex-direction: column; max-height: 85vh; width: min(680px, 92vw); }
|
||||||
|
#quick-scroll { flex: 1 1 auto; min-height: 4rem; overflow-y: auto; margin-top: 0.6rem; }
|
||||||
|
#quick-results { margin: 0; }
|
||||||
|
#quick-foot { flex: none; border-top: 1px solid var(--border); margin-top: 0.6rem; padding-top: 0.6rem; }
|
||||||
|
#quick-manual > summary { cursor: pointer; color: var(--accent); font-size: 0.9rem; padding: 0.2rem 0; }
|
||||||
|
#quick-manual[open] > summary { margin-bottom: 0.3rem; }
|
||||||
|
.quick-manual-fields { display: flex; gap: 0.6rem; flex-wrap: wrap; }
|
||||||
|
.quick-manual-fields label { flex: 1 1 10rem; margin: 0.2rem 0; }
|
||||||
|
.quick-manual-fields label.narrow { flex: 0 0 6.5rem; }
|
||||||
|
.quick-manual-fields input { min-width: 0; width: 100%; }
|
||||||
|
#quick-search-form { gap: 0.5rem; }
|
||||||
|
#quick-q { flex: 1 1 auto; min-width: 0; }
|
||||||
|
#quick-file { word-break: break-word; }
|
||||||
|
/* one row per hit: cover | title + meta line | action */
|
||||||
|
#quick-results .card { align-items: center; gap: 0.7rem; padding: 0.45rem 0.6rem; }
|
||||||
|
#quick-results .card-body { flex: 1 1 auto; gap: 0.1rem; }
|
||||||
|
#quick-results .card-body strong { line-height: 1.25; }
|
||||||
|
#quick-results .card-body .muted { font-size: 0.78rem; }
|
||||||
|
#quick-results .card > button { flex: none; }
|
||||||
.ok { color: var(--ok); }
|
.ok { color: var(--ok); }
|
||||||
.error { color: #e08585; }
|
.error { color: #e08585; }
|
||||||
#toast { position: fixed; bottom: 1.2rem; right: 1.2rem; background: var(--accent); color: #fff; padding: 0.7rem 1.1rem; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.4); z-index: 10; }
|
#toast { position: fixed; bottom: 1.2rem; right: 1.2rem; background: var(--accent); color: #fff; padding: 0.7rem 1.1rem; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.4); z-index: 10; }
|
||||||
|
|||||||
Reference in New Issue
Block a user