forked from akai/readest
mobile: fix annotator tools in iOS browsers (#239)
* chore: disable PWA in dev mode for better performance * mobile: fix annotator tools in iOS browsers
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import withPWA from 'next-pwa';
|
||||
|
||||
const isDev = process.env['NODE_ENV'] === 'development';
|
||||
const appPlatform = process.env['NEXT_PUBLIC_APP_PLATFORM'];
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
@@ -22,7 +23,7 @@ const nextConfig = {
|
||||
|
||||
export default withPWA({
|
||||
dest: 'public',
|
||||
disable: appPlatform !== 'web',
|
||||
disable: isDev || appPlatform !== 'web',
|
||||
register: true,
|
||||
skipWaiting: true,
|
||||
})(nextConfig);
|
||||
|
||||
@@ -4,6 +4,7 @@ import PopupButton from './PopupButton';
|
||||
import HighlightOptions from './HighlightOptions';
|
||||
import { Position } from '@/utils/sel';
|
||||
import { HighlightColor, HighlightStyle } from '@/types/book';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
interface AnnotationPopupProps {
|
||||
buttons: Array<{ tooltipText: string; Icon: React.ElementType; onClick: () => void }>;
|
||||
@@ -17,8 +18,8 @@ interface AnnotationPopupProps {
|
||||
onHighlight: (update?: boolean) => void;
|
||||
}
|
||||
|
||||
const highlightOptionsHeightPx = 28;
|
||||
const highlightOptionsPaddingPx = 16;
|
||||
const OPTIONS_HEIGHT_PIX = 28;
|
||||
const OPTIONS_PADDING_PIX = 16;
|
||||
|
||||
const AnnotationPopup: React.FC<AnnotationPopupProps> = ({
|
||||
buttons,
|
||||
@@ -31,6 +32,8 @@ const AnnotationPopup: React.FC<AnnotationPopupProps> = ({
|
||||
popupHeight,
|
||||
onHighlight,
|
||||
}) => {
|
||||
const highlightOptionsHeightPx = useResponsiveSize(OPTIONS_HEIGHT_PIX);
|
||||
const highlightOptionsPaddingPx = useResponsiveSize(OPTIONS_PADDING_PIX);
|
||||
return (
|
||||
<div>
|
||||
<Popup
|
||||
|
||||
@@ -35,7 +35,6 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const { settings } = useSettingsStore();
|
||||
const { getConfig, saveConfig, getBookData, updateBooknotes } = useBookDataStore();
|
||||
const { getProgress, getView, getViewsById, getViewSettings } = useReaderStore();
|
||||
const { isNotebookPinned, isNotebookVisible } = useNotebookStore();
|
||||
const { setNotebookVisible, setNotebookNewAnnotation } = useNotebookStore();
|
||||
|
||||
useNotesSync(bookKey);
|
||||
@@ -48,6 +47,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
|
||||
const isShowingPopup = useRef(false);
|
||||
const isTextSelected = useRef(false);
|
||||
const isClickToShowPopup = useRef(false);
|
||||
const [selection, setSelection] = useState<TextSelection | null>();
|
||||
const [showAnnotPopup, setShowAnnotPopup] = useState(false);
|
||||
const [showWiktionaryPopup, setShowWiktionaryPopup] = useState(false);
|
||||
@@ -86,8 +86,12 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
setSelection({ key: bookKey, text: sel.toString(), range: sel.getRangeAt(0), index });
|
||||
}
|
||||
};
|
||||
const handleTouchmove = () => {
|
||||
setShowAnnotPopup(false);
|
||||
};
|
||||
if (bookData.book?.format !== 'PDF') {
|
||||
detail.doc?.addEventListener('pointerup', handlePointerup);
|
||||
detail.doc?.addEventListener('touchmove', handleTouchmove);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -116,6 +120,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const annotation = annotations.find((annotation) => annotation.cfi === cfi);
|
||||
if (!annotation) return;
|
||||
const selection = { key: bookKey, annotated: true, text: annotation.text ?? '', range, index };
|
||||
isClickToShowPopup.current = true;
|
||||
setSelectedStyle(annotation.style!);
|
||||
setSelectedColor(annotation.color!);
|
||||
setSelection(selection);
|
||||
@@ -140,12 +145,16 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
|
||||
useEffect(() => {
|
||||
const handleSingleClick = (): boolean => {
|
||||
if (isClickToShowPopup.current) {
|
||||
isClickToShowPopup.current = false;
|
||||
return true;
|
||||
}
|
||||
if (isTextSelected.current) {
|
||||
view?.deselect();
|
||||
isTextSelected.current = false;
|
||||
handleDismissPopupAndSelection();
|
||||
return true;
|
||||
}
|
||||
if (showAnnotPopup || isShowingPopup.current) {
|
||||
handleDismissPopup();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -229,7 +238,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
});
|
||||
|
||||
const { booknotes: annotations = [] } = config;
|
||||
if (selection) navigator.clipboard.writeText(selection.text);
|
||||
if (selection) navigator.clipboard?.writeText(selection.text);
|
||||
const cfi = view?.getCFI(selection.index, selection.range);
|
||||
if (!cfi) return;
|
||||
const annotation: BookNote = {
|
||||
@@ -363,14 +372,6 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{(showAnnotPopup || showWiktionaryPopup || showWikipediaPopup || showDeepLPopup) &&
|
||||
(!isNotebookVisible || isNotebookPinned) && (
|
||||
<div
|
||||
className='fixed inset-0'
|
||||
onClick={handleDismissPopupAndSelection}
|
||||
onContextMenu={handleDismissPopup}
|
||||
/>
|
||||
)}
|
||||
{showWiktionaryPopup && trianglePosition && dictPopupPosition && (
|
||||
<WiktionaryPopup
|
||||
word={selection?.text as string}
|
||||
|
||||
@@ -25,7 +25,9 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
|
||||
const globalReadSettings = settings.globalReadSettings;
|
||||
const [selectedStyle, setSelectedStyle] = React.useState<HighlightStyle>(_selectedStyle);
|
||||
const [selectedColor, setSelectedColor] = React.useState<HighlightColor>(_selectedColor);
|
||||
const iconSize16 = useResponsiveSize(16);
|
||||
const size16 = useResponsiveSize(16);
|
||||
const size18 = useResponsiveSize(18);
|
||||
const size28 = useResponsiveSize(28);
|
||||
|
||||
const handleSelectStyle = (style: HighlightStyle) => {
|
||||
globalReadSettings.highlightStyle = style;
|
||||
@@ -42,18 +44,19 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
|
||||
onHandleHighlight(true);
|
||||
};
|
||||
return (
|
||||
<div className='highlight-options absolute flex h-7 items-center justify-between' style={style}>
|
||||
<div className='flex h-7 gap-2'>
|
||||
<div className='highlight-options absolute flex items-center justify-between' style={style}>
|
||||
<div className='flex gap-2' style={{ height: size28 }}>
|
||||
{styles.map((style) => (
|
||||
<button
|
||||
key={style}
|
||||
onClick={() => handleSelectStyle(style)}
|
||||
className={`flex h-7 min-h-7 w-7 items-center justify-center rounded-full bg-gray-700 p-0`}
|
||||
className={`flex items-center justify-center rounded-full bg-gray-700 p-0`}
|
||||
style={{ width: size28, height: size28, minHeight: size28 }}
|
||||
>
|
||||
<div
|
||||
style={{ width: size16, height: style === 'squiggly' ? size18 : size16 }}
|
||||
className={clsx(
|
||||
'w-4 p-0 text-center leading-none',
|
||||
style === 'highlight' ? 'h-4' : 'h-5',
|
||||
style === 'highlight' &&
|
||||
(selectedStyle === 'highlight' ? `bg-${selectedColor}-400` : `bg-gray-300`),
|
||||
(style === 'underline' || style === 'squiggly') &&
|
||||
@@ -74,18 +77,19 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className='flex h-7 items-center justify-center gap-2 rounded-3xl bg-gray-700 px-2'>
|
||||
<div
|
||||
className='flex items-center justify-center gap-2 rounded-3xl bg-gray-700 px-2'
|
||||
style={{ height: size28 }}
|
||||
>
|
||||
{colors.map((color) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() => handleSelectColor(color)}
|
||||
className={clsx(
|
||||
`h-4 w-4 rounded-full p-0`,
|
||||
selectedColor !== color && `bg-${color}-400`,
|
||||
)}
|
||||
style={{ width: size16, height: size16 }}
|
||||
className={clsx(`rounded-full p-0`, selectedColor !== color && `bg-${color}-400`)}
|
||||
>
|
||||
{selectedColor === color && (
|
||||
<FaCheckCircle size={iconSize16} className={clsx(`fill-${color}-400`)} />
|
||||
<FaCheckCircle size={size16} className={clsx(`fill-${color}-400`)} />
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
|
||||
+1
-1
Submodule packages/foliate-js updated: b9347d80e8...45d676baab
Reference in New Issue
Block a user