UX: make composer resize work on touch devices (#7068)
* UX: make composer resize work on touch devices This also replaces a vendor dependency with a small built-in resize mechanism. * Make blue bar's larger padding specific to touch devices
This commit is contained in:
parent
45db98dd3e
commit
d5efe2d7ee
|
@ -8,6 +8,17 @@ import positioningWorkaround from "discourse/lib/safari-hacks";
|
|||
import { headerHeight } from "discourse/components/site-header";
|
||||
import KeyEnterEscape from "discourse/mixins/key-enter-escape";
|
||||
|
||||
const START_EVENTS = "touchstart mousedown";
|
||||
const DRAG_EVENTS = "touchmove mousemove";
|
||||
const END_EVENTS = "touchend mouseup";
|
||||
|
||||
const MIN_COMPOSER_SIZE = 240;
|
||||
const THROTTLE_RATE = 20;
|
||||
|
||||
function mouseYPos(e) {
|
||||
return e.clientY || (e.touches && e.touches[0] && e.touches[0].clientY);
|
||||
}
|
||||
|
||||
export default Ember.Component.extend(KeyEnterEscape, {
|
||||
elementId: "reply-control",
|
||||
|
||||
|
@ -84,17 +95,53 @@ export default Ember.Component.extend(KeyEnterEscape, {
|
|||
}
|
||||
},
|
||||
|
||||
setupComposerResizeEvents() {
|
||||
const $composer = this.$();
|
||||
const $grippie = this.$(".grippie");
|
||||
const $document = Ember.$(document);
|
||||
let origComposerSize = 0;
|
||||
let lastMousePos = 0;
|
||||
|
||||
const performDrag = event => {
|
||||
$composer.trigger("div-resizing");
|
||||
$composer.addClass("clear-transitions");
|
||||
const currentMousePos = mouseYPos(event);
|
||||
let size = origComposerSize + (lastMousePos - currentMousePos);
|
||||
|
||||
const winHeight = Ember.$(window).height();
|
||||
size = Math.min(size, winHeight - headerHeight());
|
||||
size = Math.max(size, MIN_COMPOSER_SIZE);
|
||||
const sizePx = `${size}px`;
|
||||
this.movePanels(sizePx);
|
||||
$composer.height(sizePx);
|
||||
};
|
||||
|
||||
const throttledPerformDrag = (event => {
|
||||
event.preventDefault();
|
||||
Ember.run.throttle(this, performDrag, event, THROTTLE_RATE);
|
||||
}).bind(this);
|
||||
|
||||
const endDrag = () => {
|
||||
$document.off(DRAG_EVENTS, throttledPerformDrag);
|
||||
$document.off(END_EVENTS, endDrag);
|
||||
$composer.removeClass("clear-transitions");
|
||||
$composer.focus();
|
||||
};
|
||||
|
||||
$grippie.on(START_EVENTS, event => {
|
||||
event.preventDefault();
|
||||
origComposerSize = $composer.height();
|
||||
lastMousePos = mouseYPos(event);
|
||||
$document.on(DRAG_EVENTS, throttledPerformDrag);
|
||||
$document.on(END_EVENTS, endDrag);
|
||||
});
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
const $replyControl = $("#reply-control");
|
||||
this.setupComposerResizeEvents();
|
||||
|
||||
const resize = () => Ember.run(() => this.resize());
|
||||
|
||||
$replyControl.DivResizer({
|
||||
resize,
|
||||
maxHeight: winHeight => winHeight - headerHeight(),
|
||||
onDrag: sizePx => this.movePanels(sizePx)
|
||||
});
|
||||
|
||||
const triggerOpen = () => {
|
||||
if (this.get("composer.composeState") === Composer.OPEN) {
|
||||
this.appEvents.trigger("composer:opened");
|
||||
|
@ -102,13 +149,11 @@ export default Ember.Component.extend(KeyEnterEscape, {
|
|||
};
|
||||
triggerOpen();
|
||||
|
||||
afterTransition($replyControl, () => {
|
||||
afterTransition(this.$(), () => {
|
||||
resize();
|
||||
triggerOpen();
|
||||
});
|
||||
positioningWorkaround(this.$());
|
||||
|
||||
this.appEvents.on("composer:resize", this, this.resize);
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
typed=(action "typed")
|
||||
cancelled=(action "cancelled")
|
||||
save=(action "save")}}
|
||||
|
||||
<div class="grippie"></div>
|
||||
{{#if visible}}
|
||||
{{composer-messages composer=model
|
||||
messageCount=messageCount
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//= require Markdown.Converter.js
|
||||
//= require bootbox.js
|
||||
//= require bootstrap-modal.js
|
||||
//= require div_resizer
|
||||
//= require caret_position
|
||||
//= require favcount.js
|
||||
//= require jquery.ba-resize.js
|
||||
|
|
|
@ -67,6 +67,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
.discourse-touch {
|
||||
.open {
|
||||
.grippie {
|
||||
padding: 7px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.composer-popup-container {
|
||||
max-width: 1500px;
|
||||
margin-left: auto;
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
/**
|
||||
This is a jQuery plugin to support resizing text areas.
|
||||
|
||||
Originally based off text area resizer by Ryan O'Dell : http://plugins.jquery.com/misc/textarea.js
|
||||
|
||||
@module $.fn.DivResizer
|
||||
**/
|
||||
|
||||
var div, endDrag, grip, lastMousePos, min, mousePosition, originalDivHeight, originalPos, performDrag, startDrag, wrappedEndDrag, wrappedPerformDrag;
|
||||
div = void 0;
|
||||
originalPos = void 0;
|
||||
originalDivHeight = void 0;
|
||||
lastMousePos = 0;
|
||||
min = 230;
|
||||
grip = void 0;
|
||||
wrappedEndDrag = void 0;
|
||||
wrappedPerformDrag = void 0;
|
||||
|
||||
startDrag = function(e, opts) {
|
||||
div = $(e.data.el);
|
||||
div.addClass('clear-transitions');
|
||||
div.blur();
|
||||
lastMousePos = mousePosition(e).y;
|
||||
originalPos = lastMousePos;
|
||||
originalDivHeight = div.height();
|
||||
wrappedPerformDrag = (function() {
|
||||
return function(e) {
|
||||
return performDrag(e, opts);
|
||||
};
|
||||
})();
|
||||
wrappedEndDrag = (function() {
|
||||
return function(e) {
|
||||
return endDrag(e, opts);
|
||||
};
|
||||
})();
|
||||
$(document).mousemove(wrappedPerformDrag).mouseup(wrappedEndDrag);
|
||||
return false;
|
||||
};
|
||||
|
||||
performDrag = function(e, opts) {
|
||||
$(div).trigger("div-resizing");
|
||||
|
||||
var size, sizePx, thisMousePos;
|
||||
thisMousePos = mousePosition(e).y;
|
||||
size = originalDivHeight + (originalPos - thisMousePos);
|
||||
lastMousePos = thisMousePos;
|
||||
|
||||
var maxHeight = $(window).height();
|
||||
if (opts.maxHeight) {
|
||||
maxHeight = opts.maxHeight(maxHeight);
|
||||
}
|
||||
size = Math.min(size, maxHeight);
|
||||
size = Math.max(min, size);
|
||||
sizePx = size + "px";
|
||||
if (typeof opts.onDrag === "function") {
|
||||
opts.onDrag(sizePx);
|
||||
}
|
||||
div.height(sizePx);
|
||||
if (size < min) {
|
||||
endDrag(e, opts);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
endDrag = function(e, opts) {
|
||||
$(document).unbind("mousemove", wrappedPerformDrag).unbind("mouseup", wrappedEndDrag);
|
||||
div.removeClass('clear-transitions');
|
||||
div.focus();
|
||||
if (typeof opts.resize === "function") {
|
||||
opts.resize();
|
||||
}
|
||||
$(div).trigger("div-resized");
|
||||
div = null;
|
||||
};
|
||||
|
||||
mousePosition = function(e) {
|
||||
return {
|
||||
x: e.clientX + document.documentElement.scrollLeft,
|
||||
y: e.clientY + document.documentElement.scrollTop
|
||||
};
|
||||
};
|
||||
|
||||
$.fn.DivResizer = function(opts) {
|
||||
return this.each(function() {
|
||||
var grippie, start, staticOffset;
|
||||
div = $(this);
|
||||
if (div.hasClass("processed")) return;
|
||||
div.addClass("processed");
|
||||
staticOffset = null;
|
||||
start = function() {
|
||||
return function(e) {
|
||||
return startDrag(e, opts);
|
||||
};
|
||||
};
|
||||
grippie = div.prepend("<div class='grippie'></div>").find('.grippie').bind("mousedown", {
|
||||
el: this
|
||||
}, start());
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue