Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 70 additions & 2 deletions frontend/src/components/elevator/car.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Matter from "matter-js";
import { useEffect, useRef, useState } from "preact/hooks";
import {
BlockHeader,
Network,
Transaction,
TransactionType,
TransactionTypeEnum,
Expand All @@ -15,6 +16,8 @@ import {
import { useAtomValue } from "jotai";
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
import ElevatorCapacity from "./capacity";
import { JSX } from "preact/jsx-runtime";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";

export interface ElevatorCarProp {
transactions: Transaction[];
Expand All @@ -27,6 +30,13 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
const { transactions, blockHeader, setFromDoorClosing } = props;

const [doorClosing, setDoorClosing] = useState(false);
const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
null,
);
const [tooltipPosition, setTooltipPosition] = useState<{
x: number;
y: number;
} | null>(null);

const boxRef = useRef(null);
const canvasRef = useRef(null);
Expand Down Expand Up @@ -59,6 +69,15 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
},
});

// create mouse constraint on hover
const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse,
constraint: {
render: { visible: false },
},
});

// create two boxes and a ground
const txBoxes = transactions.map((tx, i) => {
const size = transactionSquareSize(tx.size);
Expand All @@ -72,8 +91,15 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
strokeStyle: "black",
lineWidth: 3,
},
tooltip: {
txHash: tx.tx_hash,
txSize: +tx.size,
txType: +tx.type,
txFee: +tx.fee,
FirstSeenInPool: tx.enter_pool_at,
},
label: tx.tx_hash,
});
box.label = tx.tx_hash;
return box;
});

Expand Down Expand Up @@ -118,7 +144,13 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
);

// add all of the bodies to the world
Composite.add(engine.world, [...txBoxes, ground, wall1, wall2]);
Composite.add(engine.world, [
...txBoxes,
ground,
wall1,
wall2,
mouseConstraint,
]);

// run the renderer
Render.run(render);
Expand All @@ -143,6 +175,28 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
context.fillText(`${+fee}`, x - 30, y);
}
});

// listen to mouse hover event
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
const hoveredBody = Matter.Query.point(
Matter.Composite.allBodies(engine.world),
event.mouse.position,
)[0];

if (hoveredBody?.tooltip) {
const pos = bodyToScreenPosition(hoveredBody);
setTooltipContent(
createTooltipContent(
hoveredBody.tooltip,
chainTheme as unknown as Network,
),
);
setTooltipPosition(pos);
} else {
setTooltipContent(null);
setTooltipPosition(null);
}
});
}

useEffect(() => {
Expand Down Expand Up @@ -186,6 +240,20 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
doorClosing ? "closed" : ""
}`}
>
{/* Transaction Box Tooltip 层 */}
{tooltipContent && tooltipPosition && (
<div
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
style={{
left: `${tooltipPosition.x + 15}px`,
top: `${tooltipPosition.y}px`,
transform: "translateY(-50%)",
}}
>
{tooltipContent}
</div>
)}

<div
className={`m-auto ${bgElevatorSide}`}
id="matter-js-box"
Expand Down
64 changes: 61 additions & 3 deletions frontend/src/components/pool/committed-line.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useEffect, useRef } from "preact/hooks";
import { useEffect, useRef, useState } from "preact/hooks";
import Matter from "matter-js";
import {
Network,
Transaction,
TransactionType,
TransactionTypeEnum,
} from "../../service/type";
import { FunctionalComponent } from "preact";
import { FunctionalComponent, JSX } from "preact";
import { transactionSquareSize } from "../elevator/util";
import { useAtomValue } from "jotai";
import { chainThemeAtom } from "../../states/atoms";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";

export interface CommittedLineProps {
title: string;
Expand All @@ -17,6 +21,16 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
title,
txs,
}) => {
const chainTheme = useAtomValue(chainThemeAtom);

const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
null,
);
const [tooltipPosition, setTooltipPosition] = useState<{
x: number;
y: number;
} | null>(null);

const containerRef = useRef(null);
const canvasRef = useRef(null);
const engineRef = useRef(null);
Expand Down Expand Up @@ -64,7 +78,16 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
// create two boxes and a ground
const txBoxes = txs.map((tx, i) => createTxBox(tx));

Matter.Composite.add(engine.world, [...txBoxes]);
// create mouse constraint on hover
const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse,
constraint: {
render: { visible: false },
},
});

Matter.Composite.add(engine.world, [...txBoxes, mouseConstraint]);

// run the renderer
Render.run(render);
Expand All @@ -74,6 +97,28 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({

// run the engine
Runner.run(runner, engine);

// listen to mouse hover event
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
const hoveredBody = Matter.Query.point(
Matter.Composite.allBodies(engine.world),
event.mouse.position,
)[0];

if (hoveredBody?.tooltip) {
const pos = bodyToScreenPosition(hoveredBody);
setTooltipContent(
createTooltipContent(
hoveredBody.tooltip,
chainTheme as unknown as Network,
),
);
setTooltipPosition(pos);
} else {
setTooltipContent(null);
setTooltipPosition(null);
}
});
}

useEffect(() => {
Expand All @@ -92,6 +137,19 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
<img src="/assets/svg/pool-ground.svg" alt="" />
</div>
<canvas className={`z-2 relative`} ref={canvasRef} />
{/* Transaction Box Tooltip 层 */}
{tooltipContent && tooltipPosition && (
<div
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
style={{
left: `${tooltipPosition.x + 15}px`,
top: `${tooltipPosition.y}px`,
transform: "translateY(-50%)",
}}
>
{tooltipContent}
</div>
)}
</div>
</div>
</div>
Expand Down
81 changes: 76 additions & 5 deletions frontend/src/components/pool/committing-line.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useEffect, useRef } from "preact/hooks";
import { useEffect, useRef, useState } from "preact/hooks";
import Matter from "matter-js";
import {
Network,
Transaction,
TransactionType,
TransactionTypeEnum,
} from "../../service/type";
import { FunctionalComponent } from "preact";
import { FunctionalComponent, JSX } from "preact";
import { transactionSquareSize } from "../elevator/util";
import { useAtomValue } from "jotai";
import { chainThemeAtom } from "../../states/atoms";
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";

export interface LineProps {
title: string;
Expand All @@ -17,6 +21,16 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
title,
txs,
}) => {
const chainTheme = useAtomValue(chainThemeAtom);

const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
null,
);
const [tooltipPosition, setTooltipPosition] = useState<{
x: number;
y: number;
} | null>(null);

const containerRef = useRef(null);
const canvasRef = useRef(null);
const engineRef = useRef(null);
Expand All @@ -34,8 +48,15 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
strokeStyle: "black",
lineWidth: 3,
},
tooltip: {
txHash: tx.tx_hash,
txSize: +tx.size,
txType: +tx.type,
txFee: +tx.fee,
FirstSeenInPool: tx.enter_pool_at,
},
label: tx.tx_hash,
});
box.label = tx.tx_hash;
return box;
}

Expand Down Expand Up @@ -65,6 +86,15 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
// create two boxes and a ground
const txBoxes = txs.map((tx, i) => createTxBox(tx));

// create mouse constraint on hover
const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse,
constraint: {
render: { visible: false },
},
});

// 添加示例物体
const wall1 = Matter.Bodies.rectangle(width, 0, 1, height * 2, {
isStatic: true,
Expand All @@ -87,7 +117,13 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
},
});

Matter.Composite.add(engine.world, [...txBoxes, ground, wall1, wall2]);
Matter.Composite.add(engine.world, [
...txBoxes,
ground,
wall1,
wall2,
mouseConstraint,
]);

// run the renderer
Render.run(render);
Expand All @@ -97,6 +133,28 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({

// run the engine
Runner.run(runner, engine);

// listen to mouse hover event
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
const hoveredBody = Matter.Query.point(
Matter.Composite.allBodies(engine.world),
event.mouse.position,
)[0];

if (hoveredBody?.tooltip) {
const pos = bodyToScreenPosition(hoveredBody);
setTooltipContent(
createTooltipContent(
hoveredBody.tooltip,
chainTheme as unknown as Network,
),
);
setTooltipPosition(pos);
} else {
setTooltipContent(null);
setTooltipPosition(null);
}
});
}

useEffect(() => {
Expand Down Expand Up @@ -155,8 +213,21 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
</div>
</div>

<div ref={containerRef}>
<div className={"relative"} ref={containerRef}>
<canvas ref={canvasRef} />
{/* Transaction Box Tooltip 层 */}
{tooltipContent && tooltipPosition && (
<div
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
style={{
left: `${tooltipPosition.x + 15}px`,
top: `${tooltipPosition.y}px`,
transform: "translateY(-50%)",
}}
>
{tooltipContent}
</div>
)}
</div>
<div className={"h-[300px] flex items-end"}>
<img src="/assets/svg/line-right.svg" alt="" />
Expand Down
Loading
Loading