Compare commits

...

2 Commits

Author SHA1 Message Date
root
a3a218fef1 fix: float circle releases pointer capture on pointerup/cancel so page stays responsive
All checks were successful
Release / Test backend (push) Successful in 49s
Release / Check ui (push) Successful in 1m53s
Release / Docker (push) Successful in 6m28s
Release / Gitea Release (push) Successful in 21s
2026-04-11 23:56:14 +05:00
root
0c6c3b8c43 feat: show search button on chapter reader pages
All checks were successful
Release / Test backend (push) Successful in 1m3s
Release / Check ui (push) Successful in 1m51s
Release / Docker (push) Successful in 6m16s
Release / Gitea Release (push) Successful in 25s
2026-04-11 23:37:12 +05:00
2 changed files with 17 additions and 19 deletions

View File

@@ -981,7 +981,7 @@
let floatMoved = $state(false);
function onFloatPointerDown(e: PointerEvent) {
e.preventDefault();
e.stopPropagation();
floatDragging = true;
floatMoved = false;
floatDragStart = { mx: e.clientX, my: e.clientY, ox: audioStore.floatPos.x, oy: audioStore.floatPos.y };
@@ -1000,12 +1000,14 @@
};
audioStore.floatPos = clampFloatPos(raw.x, raw.y);
}
function onFloatPointerUp() {
function onFloatPointerUp(e: PointerEvent) {
if (!floatDragging) return;
if (floatDragging && !floatMoved) {
// Tap: toggle play/pause
audioStore.toggleRequest++;
}
floatDragging = false;
try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* ignore */ }
}
// Clamp saved position to viewport on mount and on resize
@@ -1525,7 +1527,7 @@
onpointerdown={onFloatPointerDown}
onpointermove={onFloatPointerMove}
onpointerup={onFloatPointerUp}
onpointercancel={onFloatPointerUp}
onpointercancel={(e) => { floatDragging = false; try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* ignore */ } }}
>
<!-- Pulsing ring when playing -->
{#if audioStore.isPlaying}

View File

@@ -570,20 +570,18 @@
</a>
{/if}
<div class="ml-auto flex items-center gap-2">
<!-- Universal search button (hidden on chapter/reader pages) -->
{#if !/\/books\/[^/]+\/chapters\//.test(page.url.pathname)}
<button
type="button"
onclick={() => { searchOpen = true; userMenuOpen = false; langMenuOpen = false; themeMenuOpen = false; menuOpen = false; notificationsOpen = false; }}
title="Search (/ or ⌘K)"
aria-label="Search books"
class="flex items-center justify-center w-8 h-8 rounded transition-colors text-(--color-muted) hover:text-(--color-text) hover:bg-(--color-surface-2)"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
</button>
{/if}
<!-- Universal search button -->
<button
type="button"
onclick={() => { searchOpen = true; userMenuOpen = false; langMenuOpen = false; themeMenuOpen = false; menuOpen = false; notificationsOpen = false; }}
title="Search (/ or ⌘K)"
aria-label="Search books"
class="flex items-center justify-center w-8 h-8 rounded transition-colors text-(--color-muted) hover:text-(--color-text) hover:bg-(--color-surface-2)"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
</button>
<!-- Notifications bell -->
{#if data.user}
@@ -1168,8 +1166,6 @@
// Don't intercept when typing in an input/textarea
const tag = (e.target as HTMLElement).tagName;
if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement).isContentEditable) return;
// Don't open on chapter reader pages
if (/\/books\/[^/]+\/chapters\//.test(page.url.pathname)) return;
if (searchOpen) return;
// `/` key or Cmd/Ctrl+K
if (e.key === '/' || ((e.metaKey || e.ctrlKey) && e.key === 'k')) {