diff --git a/CHANGELOG.md b/CHANGELOG.md
index bdac343e75..b47e55ff05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,8 @@
([#5084](https://github.com/mitmproxy/mitmproxy/pull/5084), @Speedlulu)
* Scripts with relative paths are now loaded relative to the config file and not where the command is ran
([#4860](https://github.com/mitmproxy/mitmproxy/pull/4860), @Speedlulu)
+* Fix `mitmweb` splitter becoming drag and drop.
+ ([#6492](https://github.com/mitmproxy/mitmproxy/pull/6492), @xBZZZZ)
* Enhance documentation and add alert log messages when stream_large_bodies and modify_body are set
([#6514](https://github.com/mitmproxy/mitmproxy/pull/6514), @rosydawn6)
diff --git a/web/src/js/__tests__/components/common/SplitterSpec.tsx b/web/src/js/__tests__/components/common/SplitterSpec.tsx
index 488656d91e..fff51c7be6 100644
--- a/web/src/js/__tests__/components/common/SplitterSpec.tsx
+++ b/web/src/js/__tests__/components/common/SplitterSpec.tsx
@@ -4,87 +4,155 @@ import renderer from "react-test-renderer";
import Splitter from "../../../components/common/Splitter";
import TestUtils from "react-dom/test-utils";
-describe("Splitter Component", () => {
- it("should render correctly", () => {
- let splitter = renderer.create(),
+describe.each([
+ ["", ""],
+ ["x", "X"],
+ ["y", "Y"],
+])("Splitter Component", (axisLower, axisUpper) => {
+ if (axisLower === "") {
+ it("should render correctly with default (x) axis", () => {
+ const splitter = renderer.create(),
+ tree = splitter.toJSON();
+ expect(tree).toMatchInlineSnapshot(`
+
+`);
+ });
+ return;
+ }
+
+ it("should render correctly with specified axis", () => {
+ const splitter = renderer.create(),
tree = splitter.toJSON();
- expect(tree).toMatchSnapshot();
+ expect(tree).toMatchInlineSnapshot(`
+
+`);
});
- let splitter = TestUtils.renderIntoDocument(),
+ const splitter = TestUtils.renderIntoDocument(
+
+ ),
dom = ReactDOM.findDOMNode(splitter),
previousElementSibling = {
- offsetHeight: 0,
- offsetWidth: 0,
+ offsetWidth: 300,
+ offsetHeight: 500,
style: { flex: "" },
},
nextElementSibling = {
style: { flex: "" },
};
- it("should handle mouseDown ", () => {
- window.addEventListener = jest.fn();
- splitter.onMouseDown({ pageX: 1, pageY: 2 });
- expect(splitter.state.startX).toEqual(1);
- expect(splitter.state.startY).toEqual(2);
- expect(window.addEventListener).toBeCalledWith(
- "mousemove",
- splitter.onMouseMove
- );
- expect(window.addEventListener).toBeCalledWith(
- "mouseup",
- splitter.onMouseUp
- );
- expect(window.addEventListener).toBeCalledWith(
- "dragend",
- splitter.onDragEnd
- );
+ Object.defineProperties(dom, {
+ previousElementSibling: { value: previousElementSibling },
+ nextElementSibling: { value: nextElementSibling },
});
+ dom.firstElementChild.setPointerCapture = jest.fn();
- it("should handle dragEnd", () => {
- window.removeEventListener = jest.fn();
- splitter.onDragEnd();
- expect(dom.style.transform).toEqual("");
- expect(window.removeEventListener).toBeCalledWith(
- "dragend",
- splitter.onDragEnd
- );
- expect(window.removeEventListener).toBeCalledWith(
- "mouseup",
- splitter.onMouseUp
- );
- expect(window.removeEventListener).toBeCalledWith(
- "mousemove",
- splitter.onMouseMove
+ it("should handle pointerdown", () => {
+ const e = {
+ pageX: 13,
+ pageY: 22,
+ pointerId: -4618,
+ target: dom.firstElementChild,
+ };
+ expect(splitter.state.dragPointer).toEqual(0.1);
+ splitter.onPointerDown(e);
+ expect(e.target.setPointerCapture).toBeCalledWith(-4618);
+ expect(splitter.state.dragPointer).toEqual(-4618);
+ expect(splitter.state.startPos).toEqual(e[`page${axisUpper}`]);
+ });
+
+ it("should handle pointermove", () => {
+ const e = {
+ pageX: 62,
+ pageY: 21,
+ pointerId: -4618,
+ target: dom.firstElementChild,
+ };
+ splitter.onPointerMove(e);
+ expect(dom.style.transform).toEqual(
+ axisLower === "x"
+ ? `translateX(${62 - 13}px)`
+ : `translateY(${21 - 22}px)`
);
});
- it("should handle mouseUp", () => {
- Object.defineProperty(dom, "previousElementSibling", {
- value: previousElementSibling,
- });
- Object.defineProperty(dom, "nextElementSibling", {
- value: nextElementSibling,
- });
- splitter.onMouseUp({ pageX: 3, pageY: 4 });
- expect(splitter.state.applied).toBeTruthy();
+ it("should handle lostpointercapture", () => {
+ const e = {
+ pageX: 56,
+ pageY: 82,
+ pointerId: -4618,
+ target: dom.firstElementChild,
+ };
+ splitter.onLostPointerCapture(e);
+ expect(splitter.state.dragPointer).toEqual(0.1);
+ expect(dom.style.transform).toEqual("");
+ expect(previousElementSibling.style.flex).toEqual(
+ `0 0 ${axisLower === "x" ? 300 + 56 - 13 : 500 + 82 - 22}px`
+ );
expect(nextElementSibling.style.flex).toEqual("1 1 auto");
- expect(previousElementSibling.style.flex).toEqual("0 0 2px");
});
- it("should handle mouseMove", () => {
- splitter.onMouseMove({ pageX: 10, pageY: 10 });
- expect(dom.style.transform).toEqual("translate(9px, 0px)");
+ it("should not resize previousElementSibling negative", () => {
+ const e = {
+ pageX: 56,
+ pageY: 82,
+ pointerId: 47,
+ target: dom.firstElementChild,
+ };
+ splitter.onPointerDown(e);
+ e[`page${axisUpper}`] = -1234;
+ splitter.onLostPointerCapture(e);
+ expect(previousElementSibling.style.flex).toEqual("0 0 0px");
+ });
- let splitterY = TestUtils.renderIntoDocument();
- splitterY.onMouseMove({ pageX: 10, pageY: 10 });
- expect(ReactDOM.findDOMNode(splitterY).style.transform).toEqual(
- "translate(0px, 10px)"
+ it("should ignore other pointers", () => {
+ splitter.onPointerDown({
+ pageX: 70,
+ pageY: 60,
+ pointerId: 47,
+ target: dom.firstElementChild,
+ });
+ splitter.onPointerDown({
+ pageX: 70,
+ pageY: 60,
+ pointerId: 46,
+ target: dom.firstElementChild,
+ });
+ expect(splitter.state.dragPointer).toEqual(47);
+ splitter.onPointerMove({ pageX: 75, pageY: 55, pointerId: 46 });
+ expect(dom.style.transform).toEqual("");
+ splitter.onPointerMove({
+ pageX: 74,
+ pageY: 54,
+ pointerId: 47,
+ target: dom.firstElementChild,
+ });
+ splitter.onLostPointerCapture({ pageX: 76, pageY: 56, pointerId: 46 });
+ expect(dom.style.transform).toEqual(
+ axisLower === "x"
+ ? `translateX(${74 - 70}px)`
+ : `translateY(${54 - 60}px)`
);
});
it("should handle resize", () => {
- let x = jest.spyOn(window, "setTimeout");
+ const x = jest.spyOn(window, "setTimeout");
splitter.onResize();
expect(x).toHaveBeenCalled();
});
@@ -99,7 +167,6 @@ describe("Splitter Component", () => {
it("should handle reset", () => {
splitter.reset(false);
expect(splitter.state.applied).toBeFalsy();
-
expect(splitter.reset(true)).toEqual(undefined);
});
});
diff --git a/web/src/js/__tests__/components/common/__snapshots__/SplitterSpec.tsx.snap b/web/src/js/__tests__/components/common/__snapshots__/SplitterSpec.tsx.snap
deleted file mode 100644
index dd70ed7a7d..0000000000
--- a/web/src/js/__tests__/components/common/__snapshots__/SplitterSpec.tsx.snap
+++ /dev/null
@@ -1,12 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Splitter Component should render correctly 1`] = `
-
-`;
diff --git a/web/src/js/components/common/Splitter.tsx b/web/src/js/components/common/Splitter.tsx
index fd07f43b35..1db0d6a3ce 100644
--- a/web/src/js/components/common/Splitter.tsx
+++ b/web/src/js/components/common/Splitter.tsx
@@ -4,8 +4,9 @@ import classnames from "classnames";
type SplitterState = {
applied: boolean;
- startX: number;
- startY: number;
+ startPos: number;
+ // .dragPointer === 0.1 means not dragging
+ dragPointer: number;
};
type SplitterProps = {
@@ -17,62 +18,51 @@ export default class Splitter extends Component {
constructor(props, context) {
super(props, context);
-
- this.state = { applied: false, startX: 0, startY: 0 };
-
- this.onMouseMove = this.onMouseMove.bind(this);
- this.onMouseDown = this.onMouseDown.bind(this);
- this.onMouseUp = this.onMouseUp.bind(this);
- this.onDragEnd = this.onDragEnd.bind(this);
- }
-
- onMouseDown(e) {
- this.setState({ startX: e.pageX, startY: e.pageY });
-
- window.addEventListener("mousemove", this.onMouseMove);
- window.addEventListener("mouseup", this.onMouseUp);
- // Occasionally, only a dragEnd event is triggered, but no mouseUp.
- window.addEventListener("dragend", this.onDragEnd);
+ this.state = { applied: false, startPos: 0, dragPointer: 0.1 };
+ this.onLostPointerCapture = this.onLostPointerCapture.bind(this);
+ this.onPointerDown = this.onPointerDown.bind(this);
+ this.onPointerMove = this.onPointerMove.bind(this);
}
- onDragEnd() {
- ReactDOM.findDOMNode(this).style.transform = "";
-
- window.removeEventListener("dragend", this.onDragEnd);
- window.removeEventListener("mouseup", this.onMouseUp);
- window.removeEventListener("mousemove", this.onMouseMove);
+ onPointerDown(e) {
+ if (this.state.dragPointer !== 0.1) {
+ return;
+ }
+ e.target.setPointerCapture(e.pointerId);
+ this.setState({
+ startPos: this.props.axis === "x" ? e.pageX : e.pageY,
+ dragPointer: e.pointerId,
+ });
}
- onMouseUp(e) {
- this.onDragEnd();
-
- const node = ReactDOM.findDOMNode(this);
- const prev = node.previousElementSibling;
-
- let flexBasis = prev.offsetHeight + e.pageY - this.state.startY;
-
- if (this.props.axis === "x") {
- flexBasis = prev.offsetWidth + e.pageX - this.state.startX;
+ onLostPointerCapture(e) {
+ if (this.state.dragPointer !== e.pointerId) {
+ return;
}
+ const node = e.target.parentNode;
+ const prev = node.previousElementSibling;
- prev.style.flex = `0 0 ${Math.max(0, flexBasis)}px`;
+ node.style.transform = "";
+ prev.style.flex = `0 0 ${Math.max(
+ 0,
+ (this.props.axis === "x"
+ ? prev.offsetWidth + e.pageX
+ : prev.offsetHeight + e.pageY) - this.state.startPos
+ )}px`;
node.nextElementSibling.style.flex = "1 1 auto";
- this.setState({ applied: true });
+ this.setState({ applied: true, dragPointer: 0.1 });
this.onResize();
}
- onMouseMove(e) {
- let dX = 0;
- let dY = 0;
- if (this.props.axis === "x") {
- dX = e.pageX - this.state.startX;
- } else {
- dY = e.pageY - this.state.startY;
+ onPointerMove(e) {
+ if (this.state.dragPointer !== e.pointerId) {
+ return;
}
- ReactDOM.findDOMNode(
- this
- ).style.transform = `translate(${dX}px, ${dY}px)`;
+ e.target.parentNode.style.transform =
+ this.props.axis === "x"
+ ? `translateX(${e.pageX - this.state.startPos}px)`
+ : `translateY(${e.pageY - this.state.startPos}px)`;
}
onResize() {
@@ -116,7 +106,11 @@ export default class Splitter extends Component {
this.props.axis === "x" ? "splitter-x" : "splitter-y"
)}
>
-
+
);
}