Ignore tap zone clicks without window focus
This commit is contained in:
@@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
- (**Migration**) Show the exclude/include button only for an entry with a selected match
|
- (**Migration**) Show the exclude/include button only for an entry with a selected match
|
||||||
- (**Source/Extension**) Rename language "All" to "Multi"
|
- (**Source/Extension**) Rename language "All" to "Multi"
|
||||||
- (**Reader**) Simplify changing settings in desktop sidebar
|
- (**Reader**) Simplify changing settings in desktop sidebar
|
||||||
|
- (**Reader**) Ignore tap zone clicks while window does not have focus
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -82,10 +82,44 @@ const getScrollDirectionInvert = (
|
|||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ReaderControls {
|
class ReaderControlsClass {
|
||||||
private static updateCurrentPageTimeout: NodeJS.Timeout;
|
private updateCurrentPageTimeout: NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
static scroll(
|
private windowFocus: boolean = true;
|
||||||
|
|
||||||
|
private windowFocusUpdateImminent = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
let focusTimeout: NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
|
window.addEventListener('blur', () => {
|
||||||
|
clearTimeout(focusTimeout);
|
||||||
|
this.windowFocus = false;
|
||||||
|
this.windowFocusUpdateImminent = false;
|
||||||
|
});
|
||||||
|
window.addEventListener('focus', () => {
|
||||||
|
this.windowFocusUpdateImminent = true;
|
||||||
|
|
||||||
|
clearTimeout(focusTimeout);
|
||||||
|
focusTimeout = setTimeout(() => {
|
||||||
|
this.windowFocus = true;
|
||||||
|
this.windowFocusUpdateImminent = false;
|
||||||
|
}, d(250).milliseconds.inWholeMilliseconds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkAndUpdateWindowsFocus(): boolean {
|
||||||
|
const hasFocus = this.windowFocus;
|
||||||
|
|
||||||
|
if (this.windowFocusUpdateImminent) {
|
||||||
|
this.windowFocus = true;
|
||||||
|
this.windowFocusUpdateImminent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll(
|
||||||
offset: ScrollOffset,
|
offset: ScrollOffset,
|
||||||
direction: ScrollDirection,
|
direction: ScrollDirection,
|
||||||
readingMode: ReadingMode,
|
readingMode: ReadingMode,
|
||||||
@@ -124,12 +158,12 @@ export class ReaderControls {
|
|||||||
scrollToOptions: ScrollToOptions,
|
scrollToOptions: ScrollToOptions,
|
||||||
) => {
|
) => {
|
||||||
if (isAtStartForDirection && offset === ScrollOffset.BACKWARD && isContinuousReadingModeActive) {
|
if (isAtStartForDirection && offset === ScrollOffset.BACKWARD && isContinuousReadingModeActive) {
|
||||||
ReaderControls.openChapter('previous');
|
this.openChapter('previous');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAtEndForDirection && offset === ScrollOffset.FORWARD && isContinuousReadingModeActive) {
|
if (isAtEndForDirection && offset === ScrollOffset.FORWARD && isContinuousReadingModeActive) {
|
||||||
ReaderControls.openChapter('next');
|
this.openChapter('next');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +187,7 @@ export class ReaderControls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static openChapter(
|
openChapter(
|
||||||
offset: 'previous' | 'next' | ChapterIdInfo['id'],
|
offset: 'previous' | 'next' | ChapterIdInfo['id'],
|
||||||
doTransitionCheck: boolean = true,
|
doTransitionCheck: boolean = true,
|
||||||
scrollIntoView: boolean = true,
|
scrollIntoView: boolean = true,
|
||||||
@@ -205,7 +239,7 @@ export class ReaderControls {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (doTransitionCheck) {
|
if (doTransitionCheck) {
|
||||||
await ReaderControls.checkNextChapterConsistency(
|
await this.checkNextChapterConsistency(
|
||||||
isPreviousChapter ? 'previous' : 'next',
|
isPreviousChapter ? 'previous' : 'next',
|
||||||
currentChapter,
|
currentChapter,
|
||||||
chapterToOpen,
|
chapterToOpen,
|
||||||
@@ -247,7 +281,7 @@ export class ReaderControls {
|
|||||||
doOpenChapter().catch(defaultPromiseErrorHandler('ReaderControls#useOpenChapter'));
|
doOpenChapter().catch(defaultPromiseErrorHandler('ReaderControls#useOpenChapter'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async checkNextChapterConsistency(
|
private async checkNextChapterConsistency(
|
||||||
offset: 'previous' | 'next',
|
offset: 'previous' | 'next',
|
||||||
currentChapter: TChapterReader | null | undefined,
|
currentChapter: TChapterReader | null | undefined,
|
||||||
chapterToOpen: TChapterReader | null | undefined,
|
chapterToOpen: TChapterReader | null | undefined,
|
||||||
@@ -314,7 +348,7 @@ export class ReaderControls {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static openPage(page: number | 'previous' | 'next', forceDirection?: Direction, hideOverlay: boolean = true): void {
|
openPage(page: number | 'previous' | 'next', forceDirection?: Direction, hideOverlay: boolean = true): void {
|
||||||
const { currentPageIndex, setPageToScrollToIndex, pages, transitionPageMode, setTransitionPageMode } =
|
const { currentPageIndex, setPageToScrollToIndex, pages, transitionPageMode, setTransitionPageMode } =
|
||||||
getReaderPagesStore();
|
getReaderPagesStore();
|
||||||
const { readingDirection, readingMode, shouldShowTransitionPage } = getReaderSettingsStore();
|
const { readingDirection, readingMode, shouldShowTransitionPage } = getReaderSettingsStore();
|
||||||
@@ -365,7 +399,7 @@ export class ReaderControls {
|
|||||||
convertedPage === 'previous' &&
|
convertedPage === 'previous' &&
|
||||||
!!getReaderChaptersStore().previousChapter;
|
!!getReaderChaptersStore().previousChapter;
|
||||||
if (shouldOpenPreviousChapter) {
|
if (shouldOpenPreviousChapter) {
|
||||||
ReaderControls.openChapter('previous');
|
this.openChapter('previous');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +409,7 @@ export class ReaderControls {
|
|||||||
convertedPage === 'next' &&
|
convertedPage === 'next' &&
|
||||||
!!getReaderChaptersStore().nextChapter;
|
!!getReaderChaptersStore().nextChapter;
|
||||||
if (shouldOpenNextChapter) {
|
if (shouldOpenNextChapter) {
|
||||||
ReaderControls.openChapter('next');
|
this.openChapter('next');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,11 +440,7 @@ export class ReaderControls {
|
|||||||
setPageToScrollToIndex(isPreviousMode ? previousPageIndex : nextPageIndex);
|
setPageToScrollToIndex(isPreviousMode ? previousPageIndex : nextPageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static useUpdateCurrentPageIndex(): (
|
useUpdateCurrentPageIndex(): (pageIndex: number, debounceChapterUpdate?: boolean, endReached?: boolean) => void {
|
||||||
pageIndex: number,
|
|
||||||
debounceChapterUpdate?: boolean,
|
|
||||||
endReached?: boolean,
|
|
||||||
) => void {
|
|
||||||
const updateChapter = ReaderService.useUpdateChapter();
|
const updateChapter = ReaderService.useUpdateChapter();
|
||||||
const {
|
const {
|
||||||
settings: { downloadAheadLimit },
|
settings: { downloadAheadLimit },
|
||||||
@@ -463,9 +493,9 @@ export class ReaderControls {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
clearTimeout(ReaderControls.updateCurrentPageTimeout);
|
clearTimeout(this.updateCurrentPageTimeout);
|
||||||
if (debounceChapterUpdate) {
|
if (debounceChapterUpdate) {
|
||||||
ReaderControls.updateCurrentPageTimeout = setTimeout(
|
this.updateCurrentPageTimeout = setTimeout(
|
||||||
handleCurrentPageIndexChange,
|
handleCurrentPageIndexChange,
|
||||||
d(1).seconds.inWholeMilliseconds,
|
d(1).seconds.inWholeMilliseconds,
|
||||||
);
|
);
|
||||||
@@ -478,10 +508,10 @@ export class ReaderControls {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static updateCurrentPageOnScroll(
|
updateCurrentPageOnScroll(
|
||||||
imageRefs: MutableRefObject<(HTMLElement | null)[]>,
|
imageRefs: MutableRefObject<(HTMLElement | null)[]>,
|
||||||
lastPageIndex: number,
|
lastPageIndex: number,
|
||||||
updateCurrentPageIndex: ReturnType<typeof ReaderControls.useUpdateCurrentPageIndex>,
|
updateCurrentPageIndex: ReturnType<typeof this.useUpdateCurrentPageIndex>,
|
||||||
type: PageInViewportType,
|
type: PageInViewportType,
|
||||||
readingDirection: ReadingDirection,
|
readingDirection: ReadingDirection,
|
||||||
) {
|
) {
|
||||||
@@ -529,8 +559,8 @@ export class ReaderControls {
|
|||||||
updateCurrentPageIndex(firstVisibleImageIndex, firstVisibleImageIndex !== lastPageIndex);
|
updateCurrentPageIndex(firstVisibleImageIndex, firstVisibleImageIndex !== lastPageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static handleClick(scrollElement: HTMLElement | null, e: React.MouseEvent<HTMLDivElement, MouseEvent>): void {
|
handleClick(scrollElement: HTMLElement | null, e: React.MouseEvent<HTMLDivElement, MouseEvent>): void {
|
||||||
if (!scrollElement) {
|
if (!scrollElement || !this.checkAndUpdateWindowsFocus()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +584,7 @@ export class ReaderControls {
|
|||||||
case TapZoneRegionType.PREVIOUS:
|
case TapZoneRegionType.PREVIOUS:
|
||||||
case TapZoneRegionType.NEXT:
|
case TapZoneRegionType.NEXT:
|
||||||
if (isContinuousReadingModeActive) {
|
if (isContinuousReadingModeActive) {
|
||||||
ReaderControls.scroll(
|
this.scroll(
|
||||||
action === TapZoneRegionType.PREVIOUS ? ScrollOffset.BACKWARD : ScrollOffset.FORWARD,
|
action === TapZoneRegionType.PREVIOUS ? ScrollOffset.BACKWARD : ScrollOffset.FORWARD,
|
||||||
scrollDirection,
|
scrollDirection,
|
||||||
readingMode.value,
|
readingMode.value,
|
||||||
@@ -563,7 +593,7 @@ export class ReaderControls {
|
|||||||
scrollAmount,
|
scrollAmount,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ReaderControls.openPage(action === TapZoneRegionType.PREVIOUS ? 'previous' : 'next', 'ltr');
|
this.openPage(action === TapZoneRegionType.PREVIOUS ? 'previous' : 'next', 'ltr');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -571,7 +601,7 @@ export class ReaderControls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static useHandleProgressDragging(
|
useHandleProgressDragging(
|
||||||
progressBarRef: RefObject<HTMLDivElement | null>,
|
progressBarRef: RefObject<HTMLDivElement | null>,
|
||||||
isDragging: boolean,
|
isDragging: boolean,
|
||||||
currentPage: TReaderProgressCurrentPage,
|
currentPage: TReaderProgressCurrentPage,
|
||||||
@@ -608,7 +638,7 @@ export class ReaderControls {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderControls.openPage(newPageIndex, undefined, false);
|
this.openPage(newPageIndex, undefined, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
@@ -631,3 +661,5 @@ export class ReaderControls {
|
|||||||
}, [isDragging, currentPage, pages, progressBarPosition]);
|
}, [isDragging, currentPage, pages, progressBarPosition]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ReaderControls = new ReaderControlsClass();
|
||||||
|
|||||||
Reference in New Issue
Block a user