fix: reorganize TTS control view hierarchy, closes #1080 (#1119)

This commit is contained in:
Huang Xin
2025-05-11 18:06:15 +08:00
committed by GitHub
parent 2a624ef57a
commit 7e542e8694
4 changed files with 33 additions and 12 deletions
@@ -18,6 +18,7 @@ import Annotator from './annotator/Annotator';
import FootnotePopup from './FootnotePopup';
import HintInfo from './HintInfo';
import DoubleBorder from './DoubleBorder';
import TTSControl from './tts/TTSControl';
interface BooksGridProps {
bookKeys: string[];
@@ -42,7 +43,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
return (
<div
className={clsx('grid h-full flex-grow')}
className={clsx('relative grid h-full flex-grow')}
style={{
gridTemplateColumns: gridTemplate.columns,
gridTemplateRows: gridTemplate.rows,
@@ -161,6 +162,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
</div>
);
})}
<TTSControl />
</div>
);
};
@@ -27,7 +27,6 @@ import Spinner from '@/components/Spinner';
import SideBar from './sidebar/SideBar';
import Notebook from './notebook/Notebook';
import BooksGrid from './BooksGrid';
import TTSControl from './tts/TTSControl';
const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ ids, settings }) => {
const router = useRouter();
@@ -166,7 +165,6 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
<div className={clsx('flex', appService?.isIOSApp ? 'h-[100vh]' : 'h-dvh')}>
<SideBar onGoToLibrary={handleCloseBooksToLibrary} />
<BooksGrid bookKeys={bookKeys} onCloseBook={handleCloseBook} />
<TTSControl />
<Notebook />
{showDetailsBook && (
<BookDetailModal
@@ -16,11 +16,11 @@ const NotebookHeader: React.FC<{
const iconSize14 = useResponsiveSize(14);
return (
<div className='notebook-header relative flex h-11 items-center px-3' dir='ltr'>
<div className='absolute inset-0 flex items-center justify-center space-x-2'>
<div className='absolute inset-0 z-[-1] flex items-center justify-center space-x-2'>
<LuNotebookPen />
<div className='notebook-title hidden text-sm font-medium sm:flex'>{_('Notebook')}</div>
</div>
<div className='z-10 flex items-center gap-x-4'>
<div className='flex w-full items-center gap-x-4'>
<button
onClick={handleTogglePin}
className={clsx(
@@ -36,6 +36,8 @@ const NotebookHeader: React.FC<{
>
<MdArrowBackIosNew />
</button>
</div>
<div className='flex items-center justify-end gap-x-4'>
<button className='btn btn-ghost left-0 h-8 min-h-8 w-8 p-0'>
<FiSearch />
</button>
@@ -38,6 +38,7 @@ const TTSControl = () => {
const [timeoutTimestamp, setTimeoutTimestamp] = useState(0);
const [timeoutFunc, setTimeoutFunc] = useState<ReturnType<typeof setTimeout> | null>(null);
const viewSettings = getViewSettings(bookKey);
const popupPadding = useResponsiveSize(POPUP_PADDING);
const maxWidth = window.innerWidth - 2 * popupPadding;
const popupWidth = Math.min(maxWidth, useResponsiveSize(POPUP_WIDTH));
@@ -286,16 +287,18 @@ const TTSControl = () => {
const updatePanelPosition = () => {
if (iconRef.current) {
const rect = iconRef.current.getBoundingClientRect();
const windowRect = document.documentElement.getBoundingClientRect();
const parentRect =
iconRef.current.parentElement?.getBoundingClientRect() ||
document.documentElement.getBoundingClientRect();
const trianglePos = {
dir: 'up',
point: { x: rect.left + rect.width / 2, y: rect.top - 12 },
point: { x: rect.left + rect.width / 2 - parentRect.left, y: rect.top - 12 },
} as Position;
const popupPos = getPopupPosition(
trianglePos,
windowRect,
parentRect,
popupWidth,
popupHeight,
popupPadding,
@@ -315,8 +318,23 @@ const TTSControl = () => {
setShowPanel(false);
};
useEffect(() => {
if (!iconRef.current || !showPanel) return;
const parentElement = iconRef.current.parentElement;
if (!parentElement) return;
const resizeObserver = new ResizeObserver(() => {
updatePanelPosition();
});
resizeObserver.observe(parentElement);
return () => {
resizeObserver.disconnect();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showPanel]);
return (
<div>
<>
{showPanel && (
<div
className='fixed inset-0'
@@ -328,7 +346,8 @@ const TTSControl = () => {
<div
ref={iconRef}
className={clsx(
'fixed right-6 h-12 w-12',
'absolute h-12 w-12',
viewSettings?.rtl ? 'left-6' : 'right-6',
appService?.hasSafeAreaInset
? 'bottom-[calc(env(safe-area-inset-bottom)+70px)]'
: 'bottom-[70px] sm:bottom-14',
@@ -343,7 +362,7 @@ const TTSControl = () => {
height={popupHeight}
position={panelPosition}
trianglePosition={trianglePosition}
className='bg-base-200 absolute flex shadow-lg'
className='bg-base-200 flex shadow-lg'
>
<TTSPanel
bookKey={bookKey}
@@ -362,7 +381,7 @@ const TTSControl = () => {
/>
</Popup>
)}
</div>
</>
);
};