1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 03:50:54 +01:00

Improve Conpherence column textarea JS behaviors

Summary:
  - Don't show a loading state on the whole column while sending chat. We could show some kind of minor loading state, but standard JX.Busy stuff will kick in after a couple seconds anyway.
  - Blank the textarea immediately on submit so you can start typing more text.
  - Don't disable the form while submiting; disabling it prevents you from typing more text.
  - Hide the placeholder while the textarea is focused. If we don't do this, the placeholder reappearing after submitting text feels weird to me.

Test Plan:
  - Sent a lot of text.
  - Real fast.
  - Focused and unfocused the area.

Reviewers: btrahan, chad

Reviewed By: chad

Subscribers: epriestley

Differential Revision: https://secure.phabricator.com/D12086
This commit is contained in:
epriestley 2015-03-14 12:00:17 -07:00
parent e6f1c34a47
commit e5580d038d
4 changed files with 99 additions and 59 deletions

View file

@ -8,7 +8,7 @@
return array( return array(
'names' => array( 'names' => array(
'core.pkg.css' => 'a7f3dc55', 'core.pkg.css' => 'a7f3dc55',
'core.pkg.js' => '31bc6546', 'core.pkg.js' => '69f7e542',
'darkconsole.pkg.js' => '8ab24e01', 'darkconsole.pkg.js' => '8ab24e01',
'differential.pkg.css' => '1940be3f', 'differential.pkg.css' => '1940be3f',
'differential.pkg.js' => 'be1e5f9b', 'differential.pkg.js' => 'be1e5f9b',
@ -212,7 +212,7 @@ return array(
'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa',
'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8', 'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8',
'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4', 'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4',
'rsrc/externals/javelin/lib/Workflow.js' => '84d6aea0', 'rsrc/externals/javelin/lib/Workflow.js' => '5b2e3e2b',
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8',
'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b',
'rsrc/externals/javelin/lib/__tests__/JSON.js' => '837a7d68', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '837a7d68',
@ -352,8 +352,8 @@ return array(
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761', 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18', 'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de', 'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '0324970d', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'cff1902b',
'rsrc/js/application/conpherence/behavior-durable-column.js' => '217c5ea5', 'rsrc/js/application/conpherence/behavior-durable-column.js' => '332ac18d',
'rsrc/js/application/conpherence/behavior-menu.js' => 'c4151295', 'rsrc/js/application/conpherence/behavior-menu.js' => 'c4151295',
'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861',
'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3',
@ -517,7 +517,7 @@ return array(
'conpherence-menu-css' => 'c6ac5299', 'conpherence-menu-css' => 'c6ac5299',
'conpherence-message-pane-css' => '5930260a', 'conpherence-message-pane-css' => '5930260a',
'conpherence-notification-css' => '04a6e10a', 'conpherence-notification-css' => '04a6e10a',
'conpherence-thread-manager' => '0324970d', 'conpherence-thread-manager' => 'cff1902b',
'conpherence-update-css' => '1099a660', 'conpherence-update-css' => '1099a660',
'conpherence-widget-pane-css' => '3d575438', 'conpherence-widget-pane-css' => '3d575438',
'differential-changeset-view-css' => '6a8b172a', 'differential-changeset-view-css' => '6a8b172a',
@ -583,7 +583,7 @@ return array(
'javelin-behavior-diffusion-locate-file' => '6d3e1947', 'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => '2b228192', 'javelin-behavior-diffusion-pull-lastmodified' => '2b228192',
'javelin-behavior-doorkeeper-tag' => 'e5822781', 'javelin-behavior-doorkeeper-tag' => 'e5822781',
'javelin-behavior-durable-column' => '217c5ea5', 'javelin-behavior-durable-column' => '332ac18d',
'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-error-log' => '6882e80a',
'javelin-behavior-fancy-datepicker' => 'c51ae228', 'javelin-behavior-fancy-datepicker' => 'c51ae228',
'javelin-behavior-global-drag-and-drop' => 'bbdf75ca', 'javelin-behavior-global-drag-and-drop' => 'bbdf75ca',
@ -697,7 +697,7 @@ return array(
'javelin-view-renderer' => '6c2b09a2', 'javelin-view-renderer' => '6c2b09a2',
'javelin-view-visitor' => 'efe49472', 'javelin-view-visitor' => 'efe49472',
'javelin-websocket' => 'e292eaf4', 'javelin-websocket' => 'e292eaf4',
'javelin-workflow' => '84d6aea0', 'javelin-workflow' => '5b2e3e2b',
'lightbox-attachment-css' => '7acac05d', 'lightbox-attachment-css' => '7acac05d',
'maniphest-batch-editor' => '8f380ebc', 'maniphest-batch-editor' => '8f380ebc',
'maniphest-report-css' => 'f6931fdf', 'maniphest-report-css' => 'f6931fdf',
@ -843,16 +843,6 @@ return array(
'029a133d' => array( '029a133d' => array(
'aphront-dialog-view-css', 'aphront-dialog-view-css',
), ),
'0324970d' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
),
'03d6ed07' => array( '03d6ed07' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',
@ -973,16 +963,6 @@ return array(
'phabricator-phtize', 'phabricator-phtize',
'changeset-view-manager', 'changeset-view-manager',
), ),
'217c5ea5' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-behavior-device',
'javelin-scrollbar',
'javelin-quicksand',
'phabricator-keyboard-shortcut',
'conpherence-thread-manager',
),
'21ba5861' => array( '21ba5861' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-dom', 'javelin-dom',
@ -1074,6 +1054,16 @@ return array(
'331b1611' => array( '331b1611' => array(
'javelin-install', 'javelin-install',
), ),
'332ac18d' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-behavior-device',
'javelin-scrollbar',
'javelin-quicksand',
'phabricator-keyboard-shortcut',
'conpherence-thread-manager',
),
'3ab51e2c' => array( '3ab51e2c' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-behavior-device', 'javelin-behavior-device',
@ -1216,6 +1206,17 @@ return array(
'javelin-vector', 'javelin-vector',
'javelin-dom', 'javelin-dom',
), ),
'5b2e3e2b' => array(
'javelin-stratcom',
'javelin-request',
'javelin-dom',
'javelin-vector',
'javelin-install',
'javelin-util',
'javelin-mask',
'javelin-uri',
'javelin-routable',
),
'5c1c758c' => array( '5c1c758c' => array(
'javelin-install', 'javelin-install',
), ),
@ -1454,17 +1455,6 @@ return array(
'javelin-workflow', 'javelin-workflow',
'phabricator-draggable-list', 'phabricator-draggable-list',
), ),
'84d6aea0' => array(
'javelin-stratcom',
'javelin-request',
'javelin-dom',
'javelin-vector',
'javelin-install',
'javelin-util',
'javelin-mask',
'javelin-uri',
'javelin-routable',
),
'85ea0626' => array( '85ea0626' => array(
'javelin-install', 'javelin-install',
), ),
@ -1776,6 +1766,16 @@ return array(
'javelin-stratcom', 'javelin-stratcom',
'phabricator-phtize', 'phabricator-phtize',
), ),
'cff1902b' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
),
'd19198c8' => array( 'd19198c8' => array(
'javelin-install', 'javelin-install',
'javelin-dom', 'javelin-dom',

View file

@ -29,14 +29,18 @@ JX.install('Workflow', {
statics : { statics : {
_stack : [], _stack : [],
newFromForm : function(form, data) { newFromForm : function(form, data, keep_enabled) {
var pairs = JX.DOM.convertFormToListOfPairs(form); var pairs = JX.DOM.convertFormToListOfPairs(form);
for (var k in data) { for (var k in data) {
pairs.push([k, data[k]]); pairs.push([k, data[k]]);
} }
var inputs;
if (keep_enabled) {
inputs = [];
} else {
// Disable form elements during the request // Disable form elements during the request
var inputs = [].concat( inputs = [].concat(
JX.DOM.scry(form, 'input'), JX.DOM.scry(form, 'input'),
JX.DOM.scry(form, 'button'), JX.DOM.scry(form, 'button'),
JX.DOM.scry(form, 'textarea')); JX.DOM.scry(form, 'textarea'));
@ -47,6 +51,7 @@ JX.install('Workflow', {
inputs[ii].disabled = true; inputs[ii].disabled = true;
} }
} }
}
var workflow = new JX.Workflow(form.getAttribute('action'), {}); var workflow = new JX.Workflow(form.getAttribute('action'), {});
workflow.setDataWithListOfPairs(pairs); workflow.setDataWithListOfPairs(pairs);
@ -57,6 +62,7 @@ JX.install('Workflow', {
inputs[ii] && (inputs[ii].disabled = false); inputs[ii] && (inputs[ii].disabled = false);
} }
}); });
return workflow; return workflow;
}, },
newFromLink : function(link) { newFromLink : function(link) {

View file

@ -245,13 +245,16 @@ JX.install('ConpherenceThreadManager', {
sendMessage: function(form, params) { sendMessage: function(form, params) {
params = this._getParams(params); params = this._getParams(params);
this._willSendMessageCallback(); var keep_enabled = true;
var workflow = JX.Workflow.newFromForm(form, params)
var workflow = JX.Workflow.newFromForm(form, params, keep_enabled)
.setHandler(JX.bind(this, function(r) { .setHandler(JX.bind(this, function(r) {
this._latestTransactionID = r.latest_transaction_id; this._latestTransactionID = r.latest_transaction_id;
this._didSendMessageCallback(r); this._didSendMessageCallback(r);
})); }));
this.syncWorkflow(workflow, 'finally'); this.syncWorkflow(workflow, 'finally');
this._willSendMessageCallback();
}, },
handleDraftKeydown: function(e) { handleDraftKeydown: function(e) {

View file

@ -102,21 +102,20 @@ JX.behavior('durable-column', function(config, statics) {
JX.DOM.appendContent(messages, JX.$H(r.transactions)); JX.DOM.appendContent(messages, JX.$H(r.transactions));
scrollbar.scrollTo(messages.scrollHeight); scrollbar.scrollTo(messages.scrollHeight);
}); });
threadManager.setWillSendMessageCallback(function() { threadManager.setWillSendMessageCallback(function() {
_markLoading(true); // Wipe the textarea immediately so the user can start typing more text.
var textarea = _getColumnTextareaNode();
textarea.value = '';
_focusColumnTextareaNode();
}); });
threadManager.setDidSendMessageCallback(function(r) { threadManager.setDidSendMessageCallback(function(r) {
var messages = _getColumnMessagesNode(); var messages = _getColumnMessagesNode();
JX.DOM.appendContent(messages, JX.$H(r.transactions)); JX.DOM.appendContent(messages, JX.$H(r.transactions));
scrollbar.scrollTo(messages.scrollHeight); scrollbar.scrollTo(messages.scrollHeight);
var textarea = _getColumnTextareaNode();
textarea.value = '';
_markLoading(false);
_focusColumnTextareaNode();
}); });
threadManager.setWillUpdateWorkflowCallback(function() { threadManager.setWillUpdateWorkflowCallback(function() {
JX.Stratcom.invoke('notification-panel-close'); JX.Stratcom.invoke('notification-panel-close');
}); });
@ -289,10 +288,20 @@ JX.behavior('durable-column', function(config, statics) {
if (e.getSpecialKey() != 'return') { if (e.getSpecialKey() != 'return') {
return; return;
} }
var raw = e.getRawEvent(); var raw = e.getRawEvent();
if (raw.shiftKey) { if (raw.shiftKey) {
// If the shift key is pressed, let the browser write a newline into
// the textarea.
return; return;
} }
var textarea = _getColumnTextareaNode();
if (!textarea.value.length) {
// If there's no text, don't try to submit the form.
return;
}
_sendMessage(e); _sendMessage(e);
}); });
@ -303,6 +312,28 @@ JX.behavior('durable-column', function(config, statics) {
threadManager.handleDraftKeydown(e); threadManager.handleDraftKeydown(e);
}); });
// HTML5 placeholders are rendered as long as the input is empty, even if the
// input is currently focused. This is undesirable for the chat input,
// especially immediately after sending a message. Hide the placeholder while
// the input is focused.
JX.Stratcom.listen(
['focus', 'blur'],
'conpherence-durable-column-textarea',
function (e) {
var node = e.getTarget();
if (e.getType() == 'focus') {
if (node.placeholder) {
node.placeholderStorage = node.placeholder;
node.placeholder = '';
}
} else {
if (node.placeholderStorage) {
node.placeholder = node.placeholderStorage;
node.placeholderStorage = '';
}
}
});
if (config.visible) { if (config.visible) {
var device = JX.Device.getDevice(); var device = JX.Device.getDevice();
if (device == 'desktop') { if (device == 'desktop') {