Skip to content

Commit

Permalink
Correctly handle scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
Kitenite committed Jun 28, 2024
1 parent 1e46ff9 commit a47fc10
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 52 deletions.
28 changes: 28 additions & 0 deletions src/lib/editor/elementManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export class ElementManager {
private hoveredElement: string | undefined
private selectedElements: string[] = []

get hovered() {
return this.hoveredElement;
}

get selected() {
return this.selectedElements;
}

setHoveredElement(selector: string) {
this.hoveredElement = selector;
}

addSelectedElement(selector: string) {
this.selectedElements.push(selector);
}

removeSelectedElement(selector: string) {
this.selectedElements = this.selectedElements.filter((el) => el !== selector);
}

clearSelectedElements() {
this.selectedElements = [];
}
}
96 changes: 61 additions & 35 deletions src/lib/editor/eventHandler.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,78 @@
import { ElementMetadata } from 'common/models';
import { ElementManager } from './elementManager';
import { OverlayManager } from './overlay';

export class WebviewEventHandler {
eventCallbackMap: Record<string, (e: any) => void>
overlayManager: OverlayManager;
elementManager: ElementManager;

constructor(overlayManager: OverlayManager) {
constructor(overlayManager: OverlayManager, elementManager: ElementManager) {
this.handleIpcMessage = this.handleIpcMessage.bind(this);
this.handleConsoleMessage = this.handleConsoleMessage.bind(this);

this.overlayManager = overlayManager;
this.elementManager = elementManager;
this.eventCallbackMap = {
'mouseover': (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}

const sourceWebview = e.target as Electron.WebviewTag;
const elementMetadata: ElementMetadata = JSON.parse(e.args[0]);
const adjustedRect = overlayManager.adaptRectFromSourceElement(elementMetadata.rect, sourceWebview);
overlayManager.updateHoverRect(adjustedRect);
},
'click': (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}

const sourceWebview = e.target as Electron.WebviewTag;
const elementMetadata: ElementMetadata = JSON.parse(e.args[0]);
const adjustedRect = overlayManager.adaptRectFromSourceElement(elementMetadata.rect, sourceWebview);
overlayManager.removeClickedRects();
overlayManager.addClickRect(adjustedRect, elementMetadata.computedStyle);
},
'wheel': (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}
const scrollPosition: { x: number, y: number } = JSON.parse(e.args[0]);
overlayManager.updateScroll(scrollPosition);
},
'mouseover': this.handleMouseover(),
'click': this.handleClick(),
'wheel': this.handleScroll(),
'scroll': this.handleScroll()
};
}

handleScroll() {
return (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}
this.overlayManager.clear();
const sourceWebview = e.target as Electron.WebviewTag;
const clickedSelectors = this.elementManager.selected;
clickedSelectors.forEach(async (selector) => {
const rect = await this.overlayManager.getRectFromSelector(selector, sourceWebview);
const computedStyle = await this.overlayManager.getComputedStyleFromSelector(selector, sourceWebview);
const adjustedRect = this.overlayManager.adaptRectFromSourceElement(rect, sourceWebview);
this.overlayManager.addClickRect(adjustedRect, computedStyle);
});
};
}

handleMouseover() {
return (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}

const sourceWebview = e.target as Electron.WebviewTag;
const elementMetadata: ElementMetadata = JSON.parse(e.args[0]);
const adjustedRect = this.overlayManager.adaptRectFromSourceElement(elementMetadata.rect, sourceWebview);

this.overlayManager.updateHoverRect(adjustedRect);
this.elementManager.setHoveredElement(elementMetadata.selector);
};
}

handleClick() {
return (e: Electron.IpcMessageEvent) => {
if (!e.args || e.args.length === 0) {
console.error('No args found for mouseover event');
return;
}

const sourceWebview = e.target as Electron.WebviewTag;
const elementMetadata: ElementMetadata = JSON.parse(e.args[0]);
const adjustedRect = this.overlayManager.adaptRectFromSourceElement(elementMetadata.rect, sourceWebview);

this.overlayManager.removeClickedRects();
this.overlayManager.addClickRect(adjustedRect, elementMetadata.computedStyle);
this.elementManager.clearSelectedElements();
this.elementManager.addSelectedElement(elementMetadata.selector);
};
}

handleIpcMessage(e: Electron.IpcMessageEvent) {
console.log('ipc-message', e);
const eventHandler = this.eventCallbackMap[e.channel]
if (!eventHandler) {
console.error(`No event handler found for ${e.channel}`);
Expand All @@ -58,4 +85,3 @@ export class WebviewEventHandler {
console.log(`%c ${e.message}`, 'background: #000; color: #AAFF00');
}
}

22 changes: 11 additions & 11 deletions src/lib/editor/overlay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export class OverlayManager {
return { top, left };
}

getRectFromSelector(selector: string, sourceWebview: Electron.WebviewTag) {
return sourceWebview.executeJavaScript(`document.querySelector('${selector}').getBoundingClientRect().toJSON()`, true)
}

getComputedStyleFromSelector(selector: string, sourceWebview: Electron.WebviewTag) {
return sourceWebview.executeJavaScript(`getComputedStyle(document.querySelector('${selector}'))`, true)
}

adaptRectFromSourceElement(rect: DOMRect, sourceWebview: Electron.WebviewTag) {
const commonAncestor = this.overlayContainer?.parentElement as HTMLElement;
const sourceOffset = this.getRelativeOffset(sourceWebview, commonAncestor);
Expand Down Expand Up @@ -81,20 +89,12 @@ export class OverlayManager {
this.removeEditRect()
}

updateScroll = ({ x, y }: { x: number, y: number }) => {
this.scrollPosition = { x, y }
this.hoverRect.applyScroll(x, y)
this.clickedRects.forEach(clickRect => {
clickRect.applyScroll(x, y)
})
}

addClickRect = (rect: DOMRect, computerStyle: CSSStyleDeclaration) => {
addClickRect = (rect: DOMRect, computedStyle: CSSStyleDeclaration) => {
const clickRect = new ClickRect()
this.appendRectToPopover(clickRect.element)
this.clickedRects.push(clickRect)
const margin = computerStyle.margin
const padding = computerStyle.padding
const margin = computedStyle.margin
const padding = computedStyle.padding
clickRect.render({ width: rect.width, height: rect.height, top: rect.top, left: rect.left, padding, margin });
}

Expand Down
5 changes: 0 additions & 5 deletions src/lib/editor/overlay/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ export class RectImpl implements Rect {
this.rectElement.setAttribute('height', height.toString())
this.element.style.top = `${top}px`
this.element.style.left = `${left}px`
this.element.style.transform = 'translate(0, 0)'
}

applyScroll(scrollX: number, scrollY: number) {
this.element.style.transform = `translate(${-scrollX}px, ${-scrollY}px)`
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/routes/project/webview/WebviewArea.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ElementManager } from '@/lib/editor/elementManager';
import { WebviewEventHandler } from '@/lib/editor/eventHandler';
import { WebviewMessageBridge } from '@/lib/editor/messageBridge';
import { OverlayManager } from '@/lib/editor/overlay';
Expand All @@ -7,8 +8,9 @@ import Overlay from './Overlay';
import Webview from './Webview';

function WebviewArea() {
const elementManager = new ElementManager();
const overlayManager = new OverlayManager();
const webviewEventHandler = new WebviewEventHandler(overlayManager);
const webviewEventHandler = new WebviewEventHandler(overlayManager, elementManager);
const webviewMessageBridge = new WebviewMessageBridge(webviewEventHandler);
const webviews: WebviewMetadata[] = [
{
Expand Down

0 comments on commit a47fc10

Please sign in to comment.