Skip to content

Commit

Permalink
FIX: allows to resize panels on tablets (#22640)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jjaffeux committed Jul 17, 2023
1 parent fe8d9b6 commit a982b67
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 29 deletions.
@@ -1,10 +1,13 @@
import Modifier from "ember-modifier";
import { registerDestructor } from "@ember/destroyable";
import { bind } from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";

const MINIMUM_SIZE = 20;

export default class ResizableNode extends Modifier {
@service capabilities;

element = null;
resizerSelector = null;
didResizeContainer = null;
Expand All @@ -14,8 +17,8 @@ export default class ResizableNode extends Modifier {
_originalHeight = 0;
_originalX = 0;
_originalY = 0;
_originalMouseX = 0;
_originalMouseY = 0;
_originalPageX = 0;
_originalPageY = 0;

constructor(owner, args) {
super(owner, args);
Expand All @@ -31,15 +34,27 @@ export default class ResizableNode extends Modifier {
options
);

this.element
.querySelector(this.resizerSelector)
?.addEventListener("mousedown", this._startResize);
if (this.capabilities.touch) {
this.element
.querySelector(this.resizerSelector)
?.addEventListener("touchstart", this._startResize);
} else {
this.element
.querySelector(this.resizerSelector)
?.addEventListener("mousedown", this._startResize);
}
}

cleanup() {
this.element
.querySelector(this.resizerSelector)
?.removeEventListener("mousedown", this._startResize);
if (this.capabilities.touch) {
this.element
.querySelector(this.resizerSelector)
?.addEventListener("touchstart", this._startResize);
} else {
this.element
.querySelector(this.resizerSelector)
?.removeEventListener("mousedown", this._startResize);
}
}

@bind
Expand All @@ -58,19 +73,25 @@ export default class ResizableNode extends Modifier {
);
this._originalX = this.element.getBoundingClientRect().left;
this._originalY = this.element.getBoundingClientRect().top;
this._originalMouseX = event.pageX;
this._originalMouseY = event.pageY;

window.addEventListener("mousemove", this._resize);
window.addEventListener("mouseup", this._stopResize);
this._originalPageX = this._eventValueForProperty(event, "pageX");
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
based on the current mouse position: width is calculated by subtracting
the difference between the current event.pageX and the original this._originalMouseX
based on the current position on page: width is calculated by subtracting
the difference between the current pageX and the original this._originalPageX
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:
Expand All @@ -83,15 +104,17 @@ export default class ResizableNode extends Modifier {
@bind
_resize(event) {
let width = this._originalWidth;
let diffWidth = event.pageX - this._originalMouseX;
let diffWidth =
this._eventValueForProperty(event, "pageX") - this._originalPageX;
if (document.documentElement.classList.contains("rtl")) {
width = Math.ceil(width + diffWidth);
} else {
width = Math.ceil(width - diffWidth);
}

const height = Math.ceil(
this._originalHeight - (event.pageY - this._originalMouseY)
this._originalHeight -
(this._eventValueForProperty(event, "pageY") - this._originalPageY)
);

const newStyle = {};
Expand All @@ -101,8 +124,11 @@ export default class ResizableNode extends Modifier {

if (this.options.position) {
newStyle.left =
Math.ceil(this._originalX + (event.pageX - this._originalMouseX)) +
"px";
Math.ceil(
this._originalX +
(this._eventValueForProperty(event, "pageX") -
this._originalPageX)
) + "px";
}
}

Expand All @@ -111,8 +137,11 @@ export default class ResizableNode extends Modifier {

if (this.options.position) {
newStyle.top =
Math.ceil(this._originalY + (event.pageY - this._originalMouseY)) +
"px";
Math.ceil(
this._originalY +
(this._eventValueForProperty(event, "pageY") -
this._originalPageY)
) + "px";
}
}

Expand All @@ -125,7 +154,20 @@ export default class ResizableNode extends Modifier {

@bind
_stopResize() {
window.removeEventListener("mousemove", this._resize);
window.removeEventListener("mouseup", this._stopResize);
if (this.capabilities.touch) {
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 {
top: 0;
bottom: 0;
left: -3px;
width: 5px;

position: absolute;
z-index: calc(z("header") - 1);
transition: background-color 0.15s 0.15s;
background-color: transparent;

&:hover,
&:active {
cursor: col-resize;
background: var(--tertiary);
.touch & {
left: -6px;
width: 10px;

&:active {
cursor: col-resize;
background: var(--tertiary);
}
}

.no-touch & {
left: -3px;
width: 5px;

&:hover,
&:active {
cursor: col-resize;
background: var(--tertiary);
}
}
}

0 comments on commit a982b67

Please sign in to comment.