FIX: allows to resize panels on tablets (#22640)
On tablets like iPad where we allow channel and thread to be on the same screen, it was not possible to resize the panels due to code being thought for mouse events. This commit should now correctly allow for this. The "resizer" has also been made larger to simplify touching. No test as it's hard to test on iPad and dragging events are also complex.
This commit is contained in:
parent
fe8d9b6b4e
commit
a982b6765f
|
@ -1,10 +1,13 @@
|
||||||
import Modifier from "ember-modifier";
|
import Modifier from "ember-modifier";
|
||||||
import { registerDestructor } from "@ember/destroyable";
|
import { registerDestructor } from "@ember/destroyable";
|
||||||
import { bind } from "discourse-common/utils/decorators";
|
import { bind } from "discourse-common/utils/decorators";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
|
||||||
const MINIMUM_SIZE = 20;
|
const MINIMUM_SIZE = 20;
|
||||||
|
|
||||||
export default class ResizableNode extends Modifier {
|
export default class ResizableNode extends Modifier {
|
||||||
|
@service capabilities;
|
||||||
|
|
||||||
element = null;
|
element = null;
|
||||||
resizerSelector = null;
|
resizerSelector = null;
|
||||||
didResizeContainer = null;
|
didResizeContainer = null;
|
||||||
|
@ -14,8 +17,8 @@ export default class ResizableNode extends Modifier {
|
||||||
_originalHeight = 0;
|
_originalHeight = 0;
|
||||||
_originalX = 0;
|
_originalX = 0;
|
||||||
_originalY = 0;
|
_originalY = 0;
|
||||||
_originalMouseX = 0;
|
_originalPageX = 0;
|
||||||
_originalMouseY = 0;
|
_originalPageY = 0;
|
||||||
|
|
||||||
constructor(owner, args) {
|
constructor(owner, args) {
|
||||||
super(owner, args);
|
super(owner, args);
|
||||||
|
@ -31,15 +34,27 @@ export default class ResizableNode extends Modifier {
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
|
||||||
this.element
|
if (this.capabilities.touch) {
|
||||||
.querySelector(this.resizerSelector)
|
this.element
|
||||||
?.addEventListener("mousedown", this._startResize);
|
.querySelector(this.resizerSelector)
|
||||||
|
?.addEventListener("touchstart", this._startResize);
|
||||||
|
} else {
|
||||||
|
this.element
|
||||||
|
.querySelector(this.resizerSelector)
|
||||||
|
?.addEventListener("mousedown", this._startResize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
this.element
|
if (this.capabilities.touch) {
|
||||||
.querySelector(this.resizerSelector)
|
this.element
|
||||||
?.removeEventListener("mousedown", this._startResize);
|
.querySelector(this.resizerSelector)
|
||||||
|
?.addEventListener("touchstart", this._startResize);
|
||||||
|
} else {
|
||||||
|
this.element
|
||||||
|
.querySelector(this.resizerSelector)
|
||||||
|
?.removeEventListener("mousedown", this._startResize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
|
@ -58,19 +73,25 @@ export default class ResizableNode extends Modifier {
|
||||||
);
|
);
|
||||||
this._originalX = this.element.getBoundingClientRect().left;
|
this._originalX = this.element.getBoundingClientRect().left;
|
||||||
this._originalY = this.element.getBoundingClientRect().top;
|
this._originalY = this.element.getBoundingClientRect().top;
|
||||||
this._originalMouseX = event.pageX;
|
|
||||||
this._originalMouseY = event.pageY;
|
|
||||||
|
|
||||||
window.addEventListener("mousemove", this._resize);
|
this._originalPageX = this._eventValueForProperty(event, "pageX");
|
||||||
window.addEventListener("mouseup", this._stopResize);
|
this._originalPageY = this._eventValueForProperty(event, "pageY");
|
||||||
|
|
||||||
|
if (this.capabilities.touch) {
|
||||||
|
window.addEventListener("touchmove", this._resize);
|
||||||
|
window.addEventListener("touchend", this._stopResize);
|
||||||
|
} else {
|
||||||
|
window.addEventListener("mousemove", this._resize);
|
||||||
|
window.addEventListener("mouseup", this._stopResize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The bulk of the logic is to calculate the new width and height of the element
|
The bulk of the logic is to calculate the new width and height of the element
|
||||||
based on the current mouse position: width is calculated by subtracting
|
based on the current position on page: width is calculated by subtracting
|
||||||
the difference between the current event.pageX and the original this._originalMouseX
|
the difference between the current pageX and the original this._originalPageX
|
||||||
from the original this._originalWidth, and rounding up to the nearest integer.
|
from the original this._originalWidth, and rounding up to the nearest integer.
|
||||||
height is calculated in a similar way using event.pageY and this._originalMouseY.
|
height is calculated in a similar way using pageY and this._originalPageY.
|
||||||
|
|
||||||
In this example (B) is the current element top/left and (A) is x/y of the mouse after dragging:
|
In this example (B) is the current element top/left and (A) is x/y of the mouse after dragging:
|
||||||
|
|
||||||
|
@ -83,7 +104,8 @@ export default class ResizableNode extends Modifier {
|
||||||
@bind
|
@bind
|
||||||
_resize(event) {
|
_resize(event) {
|
||||||
let width = this._originalWidth;
|
let width = this._originalWidth;
|
||||||
let diffWidth = event.pageX - this._originalMouseX;
|
let diffWidth =
|
||||||
|
this._eventValueForProperty(event, "pageX") - this._originalPageX;
|
||||||
if (document.documentElement.classList.contains("rtl")) {
|
if (document.documentElement.classList.contains("rtl")) {
|
||||||
width = Math.ceil(width + diffWidth);
|
width = Math.ceil(width + diffWidth);
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,7 +113,8 @@ export default class ResizableNode extends Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
const height = Math.ceil(
|
const height = Math.ceil(
|
||||||
this._originalHeight - (event.pageY - this._originalMouseY)
|
this._originalHeight -
|
||||||
|
(this._eventValueForProperty(event, "pageY") - this._originalPageY)
|
||||||
);
|
);
|
||||||
|
|
||||||
const newStyle = {};
|
const newStyle = {};
|
||||||
|
@ -101,8 +124,11 @@ export default class ResizableNode extends Modifier {
|
||||||
|
|
||||||
if (this.options.position) {
|
if (this.options.position) {
|
||||||
newStyle.left =
|
newStyle.left =
|
||||||
Math.ceil(this._originalX + (event.pageX - this._originalMouseX)) +
|
Math.ceil(
|
||||||
"px";
|
this._originalX +
|
||||||
|
(this._eventValueForProperty(event, "pageX") -
|
||||||
|
this._originalPageX)
|
||||||
|
) + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +137,11 @@ export default class ResizableNode extends Modifier {
|
||||||
|
|
||||||
if (this.options.position) {
|
if (this.options.position) {
|
||||||
newStyle.top =
|
newStyle.top =
|
||||||
Math.ceil(this._originalY + (event.pageY - this._originalMouseY)) +
|
Math.ceil(
|
||||||
"px";
|
this._originalY +
|
||||||
|
(this._eventValueForProperty(event, "pageY") -
|
||||||
|
this._originalPageY)
|
||||||
|
) + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +154,20 @@ export default class ResizableNode extends Modifier {
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
_stopResize() {
|
_stopResize() {
|
||||||
window.removeEventListener("mousemove", this._resize);
|
if (this.capabilities.touch) {
|
||||||
window.removeEventListener("mouseup", this._stopResize);
|
window.removeEventListener("touchmove", this._resize);
|
||||||
|
window.removeEventListener("touchend", this._stopResize);
|
||||||
|
} else {
|
||||||
|
window.removeEventListener("mousemove", this._resize);
|
||||||
|
window.removeEventListener("mouseup", this._stopResize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventValueForProperty(event, property) {
|
||||||
|
if (this.capabilities.touch) {
|
||||||
|
return event.changedTouches[0][property];
|
||||||
|
} else {
|
||||||
|
return event[property];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
.chat-side-panel-resizer {
|
.chat-side-panel-resizer {
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: -3px;
|
|
||||||
width: 5px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: calc(z("header") - 1);
|
z-index: calc(z("header") - 1);
|
||||||
transition: background-color 0.15s 0.15s;
|
transition: background-color 0.15s 0.15s;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:hover,
|
.touch & {
|
||||||
&:active {
|
left: -6px;
|
||||||
cursor: col-resize;
|
width: 10px;
|
||||||
background: var(--tertiary);
|
|
||||||
|
&:active {
|
||||||
|
cursor: col-resize;
|
||||||
|
background: var(--tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-touch & {
|
||||||
|
left: -3px;
|
||||||
|
width: 5px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
cursor: col-resize;
|
||||||
|
background: var(--tertiary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue