Skip to content

Commit

Permalink
feat: cause text boxes to show on mokuro reader when using the puck
Browse files Browse the repository at this point in the history
Fixes #1009.
  • Loading branch information
birtles committed Dec 2, 2022
1 parent 81d8779 commit 2f58c2a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 6 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ app.
## [Unreleased]

- Added support for parsing ざるを得ない endings, e.g. 闘わざるをえなかった.
- Added support for parsing ~ないで, e.g. 払わないですんだ
- Added support for parsing ~ないで, e.g. 払わないですんだ.
- Added an option for higher contrast pitch accent markings.
- (Chrome, Edge) Fixed the browser icon getting stuck at 100%
([#1003](https://github.com/birchill/10ten-ja-reader/issues/1003)).
Expand All @@ -18,6 +18,10 @@ app.
- Made the popup show for sites that make nested contents fullscreen such as
Crunchyroll
([#1015](https://github.com/birchill/10ten-ja-reader/issues/1015)).
- Made the touchscreen puck trigger showing text boxes on
[mokuro](https://github.com/kha-white/mokuro) that normally only show on
hover
([#1009](https://github.com/birchill/10ten-ja-reader/issues/1009)).
- Fixed lookup of Japanese inside `display: contents` containers.
- Made the copy overlay not show if the user has selected text in the popup.
- Made shogi shorthand matches not show up when there is a longer word match.
Expand Down
2 changes: 1 addition & 1 deletion src/content/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ export class ContentHandler {
// If the user pressed the hold-to-show key combination, show the popup
// if possible.
//
// It's important we only do this whehn the popup is not visible, however,
// It's important we only do this when the popup is not visible, however,
// since these keys may overlap with the keys we've defined for pinning the
// popup--which only apply when the popup is visible.
const matchedHoldToShowKeys = this.isHoldToShowKeyStroke(event);
Expand Down
109 changes: 105 additions & 4 deletions src/content/puck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,16 @@ function clearClickTimeout(clickState: ClickState) {
// furthermore looks up words.
export type PuckEnabledState = 'disabled' | 'inactive' | 'active';

type RestoreContentParams = { root: Element; restore: () => void };

export class LookupPuck {
public static id = 'tenten-ja-puck';
private puck: HTMLDivElement | undefined;
private enabledState: PuckEnabledState = 'disabled';

private clickState: ClickState = { kind: 'idle' };
private static readonly clickHysteresis = 300;

private puckX: number;
private puckY: number;
private earthWidth: number;
Expand Down Expand Up @@ -118,6 +124,11 @@ export class LookupPuck {
// present yet.
private hasBuggyPositionFixed: boolean | undefined;

// We sometimes temporarily modify the content so we can look it up. In such
// a case we register a `restore` function to return the content back
// to its original state when we have finished with it.
private contentToRestore: RestoreContentParams | undefined;

constructor(
private safeAreaProvider: SafeAreaProvider,
private onLookupDisabled: () => void
Expand Down Expand Up @@ -392,9 +403,31 @@ export class LookupPuck {
this.targetOffset.y -
viewportOffsetTop;

// See what we are pointing at
let target = document.elementFromPoint(targetX, targetY);

// Check if we need to adjust the content to look it up.
//
// But first check we aren't pointing at the same content as we adjusted
// last time (or one of its descendents).
if (!this.contentToRestore?.root.contains(target)) {
// Restore any content we previously adjusted.
this.restoreContent();

// Look for hidden textboxes on mokuro reader pages
const mokuroResult = LookupPuck.uncoverMokuroText(
target,
targetX,
targetY
);
if (mokuroResult) {
target = mokuroResult.newTarget;
this.contentToRestore = mokuroResult.contentToRestore;
}
}

// Make sure the target is an actual element since the mousemove handler
// expects that.
const target = document.elementFromPoint(targetX, targetY);
if (!target) {
return;
}
Expand Down Expand Up @@ -453,6 +486,76 @@ export class LookupPuck {
target.dispatchEvent(mouseEvent);
};

private restoreContent() {
this.contentToRestore?.restore();
this.contentToRestore = undefined;
}

// Look for textBox elements generated by mokuro reader
// (https://github.com/kha-white/mokuro) since they have hidden paragraph
// elements that are only shown on hover.
private static uncoverMokuroText(
target: Element | null,
targetX: number,
targetY: number
): { newTarget: Element; contentToRestore: RestoreContentParams } | null {
// Check for a suitable suspect
if (
!(target instanceof HTMLElement) ||
!target.classList.contains('textBox')
) {
return null;
}

// Set the paragraphs to display: table to match the hover style's from
// mokuro's stylesheet:
//
// https://github.com/kha-white/mokuro/blob/43c59a3c49100db522db088563297dc609afa031/mokuro/styles.css#L70-L72
//
// We also record the previous setting on the inline style attribute so we
// can faithfully restore it when we're done.
const paragraphs = target.querySelectorAll('p');
const toRestore: Array<[HTMLParagraphElement, string | null]> = [];
for (const p of paragraphs) {
if (getComputedStyle(p).display === 'none') {
toRestore.push([p, p.style.display || null]);
p.style.display = 'table';
}
}

// Check if we found any paragraphs to adjust
if (!toRestore.length) {
return null;
}

// Setup a function to restore the content
const restore = () => {
// If we selected part of the content we uncovered we need to clear
// selection or else we'll be unable to select anything more.
const selection = window.getSelection();
if (target && toRestore.some(([p]) => selection?.containsNode(p, true))) {
selection!.removeAllRanges();
}

// Restore the inline style display
for (const [p, display] of toRestore) {
if (display) {
p.style.display = display;
} else {
p.style.removeProperty('display');
}
}
};

const newTarget = document.elementFromPoint(targetX, targetY);
if (!newTarget) {
restore();
return null;
}

return { newTarget, contentToRestore: { root: target, restore } };
}

private readonly checkForBuggyPositionFixed = () => {
// Check if we've already run this check
if (typeof this.hasBuggyPositionFixed !== 'undefined') {
Expand Down Expand Up @@ -517,9 +620,6 @@ export class LookupPuck {
);
};

private clickState: ClickState = { kind: 'idle' };
private static readonly clickHysteresis = 300;

private readonly onPuckPointerDown = (event: PointerEvent) => {
if (this.enabledState === 'disabled' || !this.puck) {
return;
Expand Down Expand Up @@ -924,6 +1024,7 @@ export class LookupPuck {
}

unmount(): void {
this.restoreContent();
removePuck();
window.visualViewport?.removeEventListener(
'resize',
Expand Down

0 comments on commit 2f58c2a

Please sign in to comment.