mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-22 02:56:24 -07:00
fix(renderer): sync embedded sidebar mouse passthrough
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { ModalStateReader, RendererContext } from '../context';
|
||||
import { syncOverlayMouseIgnoreState } from '../overlay-mouse-ignore.js';
|
||||
import {
|
||||
YOMITAN_POPUP_HIDDEN_EVENT,
|
||||
YOMITAN_POPUP_SHOWN_EVENT,
|
||||
@@ -25,6 +26,19 @@ export function createMouseHandlers(
|
||||
let pausedBySubtitleHover = false;
|
||||
let pausedByYomitanPopup = false;
|
||||
|
||||
function isWithinOtherSubtitleContainer(
|
||||
relatedTarget: EventTarget | null,
|
||||
otherContainer: HTMLElement,
|
||||
): boolean {
|
||||
if (relatedTarget === otherContainer) {
|
||||
return true;
|
||||
}
|
||||
if (typeof Node !== 'undefined' && relatedTarget instanceof Node) {
|
||||
return otherContainer.contains(relatedTarget);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function maybeResumeHoverPause(): void {
|
||||
if (!pausedBySubtitleHover) return;
|
||||
if (pausedByYomitanPopup) return;
|
||||
@@ -80,10 +94,7 @@ export function createMouseHandlers(
|
||||
function enablePopupInteraction(): void {
|
||||
yomitanPopupVisible = true;
|
||||
ctx.state.yomitanPopupVisible = true;
|
||||
ctx.dom.overlay.classList.add('interactive');
|
||||
if (ctx.platform.shouldToggleMouseIgnore) {
|
||||
window.electronAPI.setIgnoreMouseEvents(false);
|
||||
}
|
||||
syncOverlayMouseIgnoreState(ctx);
|
||||
if (ctx.platform.isMacOSPlatform) {
|
||||
window.focus();
|
||||
}
|
||||
@@ -101,20 +112,18 @@ export function createMouseHandlers(
|
||||
popupPauseRequestId += 1;
|
||||
maybeResumeYomitanPopupPause();
|
||||
maybeResumeHoverPause();
|
||||
if (!ctx.state.isOverSubtitle && !options.modalStateReader.isAnyModalOpen()) {
|
||||
ctx.dom.overlay.classList.remove('interactive');
|
||||
if (ctx.platform.shouldToggleMouseIgnore) {
|
||||
window.electronAPI.setIgnoreMouseEvents(true, { forward: true });
|
||||
}
|
||||
}
|
||||
syncOverlayMouseIgnoreState(ctx);
|
||||
}
|
||||
|
||||
async function handleMouseEnter(): Promise<void> {
|
||||
async function handleMouseEnter(
|
||||
_event?: MouseEvent,
|
||||
showSecondaryHover = false,
|
||||
): Promise<void> {
|
||||
ctx.state.isOverSubtitle = true;
|
||||
ctx.dom.overlay.classList.add('interactive');
|
||||
if (ctx.platform.shouldToggleMouseIgnore) {
|
||||
window.electronAPI.setIgnoreMouseEvents(false);
|
||||
if (showSecondaryHover) {
|
||||
ctx.dom.secondarySubContainer.classList.add('secondary-sub-hover-active');
|
||||
}
|
||||
syncOverlayMouseIgnoreState(ctx);
|
||||
|
||||
if (yomitanPopupVisible && options.getYomitanPopupAutoPauseEnabled()) {
|
||||
return;
|
||||
@@ -124,6 +133,10 @@ export function createMouseHandlers(
|
||||
return;
|
||||
}
|
||||
|
||||
if (pausedBySubtitleHover) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestId = ++hoverPauseRequestId;
|
||||
let paused: boolean | null = null;
|
||||
try {
|
||||
@@ -141,8 +154,22 @@ export function createMouseHandlers(
|
||||
pausedBySubtitleHover = true;
|
||||
}
|
||||
|
||||
async function handleMouseLeave(): Promise<void> {
|
||||
async function handleMouseLeave(
|
||||
_event?: MouseEvent,
|
||||
hideSecondaryHover = false,
|
||||
): Promise<void> {
|
||||
const relatedTarget = _event?.relatedTarget ?? null;
|
||||
const otherContainer = hideSecondaryHover
|
||||
? ctx.dom.subtitleContainer
|
||||
: ctx.dom.secondarySubContainer;
|
||||
if (relatedTarget && isWithinOtherSubtitleContainer(relatedTarget, otherContainer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.state.isOverSubtitle = false;
|
||||
if (hideSecondaryHover) {
|
||||
ctx.dom.secondarySubContainer.classList.remove('secondary-sub-hover-active');
|
||||
}
|
||||
hoverPauseRequestId += 1;
|
||||
maybeResumeHoverPause();
|
||||
if (yomitanPopupVisible) return;
|
||||
@@ -246,6 +273,10 @@ export function createMouseHandlers(
|
||||
}
|
||||
|
||||
return {
|
||||
handlePrimaryMouseEnter: (event?: MouseEvent) => handleMouseEnter(event, false),
|
||||
handlePrimaryMouseLeave: (event?: MouseEvent) => handleMouseLeave(event, false),
|
||||
handleSecondaryMouseEnter: (event?: MouseEvent) => handleMouseEnter(event, true),
|
||||
handleSecondaryMouseLeave: (event?: MouseEvent) => handleMouseLeave(event, true),
|
||||
handleMouseEnter,
|
||||
handleMouseLeave,
|
||||
setupDragging,
|
||||
|
||||
42
src/renderer/overlay-mouse-ignore.ts
Normal file
42
src/renderer/overlay-mouse-ignore.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { RendererContext } from './context';
|
||||
import type { RendererState } from './state';
|
||||
|
||||
function isBlockingOverlayModalOpen(state: RendererState): boolean {
|
||||
const embeddedSidebarOpen =
|
||||
state.subtitleSidebarModalOpen && state.subtitleSidebarConfig?.layout === 'embedded';
|
||||
|
||||
return Boolean(
|
||||
state.controllerSelectModalOpen ||
|
||||
state.controllerDebugModalOpen ||
|
||||
state.jimakuModalOpen ||
|
||||
state.kikuModalOpen ||
|
||||
state.runtimeOptionsModalOpen ||
|
||||
state.subsyncModalOpen ||
|
||||
state.sessionHelpModalOpen ||
|
||||
(state.subtitleSidebarModalOpen && !embeddedSidebarOpen),
|
||||
);
|
||||
}
|
||||
|
||||
export function syncOverlayMouseIgnoreState(ctx: RendererContext): void {
|
||||
const shouldStayInteractive =
|
||||
ctx.state.isOverSubtitle ||
|
||||
ctx.state.isOverSubtitleSidebar ||
|
||||
ctx.state.yomitanPopupVisible ||
|
||||
isBlockingOverlayModalOpen(ctx.state);
|
||||
|
||||
if (shouldStayInteractive) {
|
||||
ctx.dom.overlay.classList.add('interactive');
|
||||
} else {
|
||||
ctx.dom.overlay.classList.remove('interactive');
|
||||
}
|
||||
if (!ctx.platform?.shouldToggleMouseIgnore) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldStayInteractive) {
|
||||
window.electronAPI.setIgnoreMouseEvents(false);
|
||||
return;
|
||||
}
|
||||
|
||||
window.electronAPI.setIgnoreMouseEvents(true, { forward: true });
|
||||
}
|
||||
@@ -25,6 +25,7 @@ export type ChordAction =
|
||||
|
||||
export type RendererState = {
|
||||
isOverSubtitle: boolean;
|
||||
isOverSubtitleSidebar: boolean;
|
||||
isDragging: boolean;
|
||||
dragStartY: number;
|
||||
startYPercent: number;
|
||||
@@ -115,6 +116,7 @@ export type RendererState = {
|
||||
export function createRendererState(): RendererState {
|
||||
return {
|
||||
isOverSubtitle: false,
|
||||
isOverSubtitleSidebar: false,
|
||||
isDragging: false,
|
||||
dragStartY: 0,
|
||||
startYPercent: 0,
|
||||
|
||||
Reference in New Issue
Block a user