Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/js/application/conpherence/behavior-durable-column.js
12242 views
1
/**
2
* @provides javelin-behavior-durable-column
3
* @requires javelin-behavior
4
* javelin-dom
5
* javelin-stratcom
6
* javelin-behavior-device
7
* javelin-scrollbar
8
* javelin-quicksand
9
* phabricator-keyboard-shortcut
10
* conpherence-thread-manager
11
*/
12
13
JX.behavior('durable-column', function(config, statics) {
14
// TODO: Currently, updating the column sends the entire column back. This
15
// includes the `durable-column` behavior itself, which tries to re-initialize
16
// the column. Detect this and bail.
17
//
18
// If ThreadManager gets separated into a UI part and a thread part (which
19
// seems likely), responses may no longer ship back the entire column. This
20
// might let us remove this check.
21
if (statics.initialized) {
22
return;
23
} else {
24
statics.initialized = true;
25
}
26
27
var userVisible = config.visible;
28
var userMinimize = config.minimize;
29
var show = null;
30
var loadThreadID = null;
31
var scrollbar = null;
32
33
var margin = JX.Scrollbar.getScrollbarControlMargin();
34
35
var quick = JX.$('phabricator-standard-page-body');
36
37
function _getColumnNode() {
38
return JX.$('conpherence-durable-column');
39
}
40
41
function _getColumnScrollNode() {
42
var column = _getColumnNode();
43
return JX.DOM.find(column, 'div', 'conpherence-durable-column-main');
44
}
45
46
function _updateColumnVisibility() {
47
var new_value = (userVisible);
48
if (new_value !== show) {
49
show = new_value;
50
_drawColumn(show);
51
}
52
}
53
54
function _toggleColumn() {
55
userVisible = !userVisible;
56
_updateColumnVisibility();
57
58
new JX.Request(config.visibleURI)
59
.setData({value: (show ? 1 : 0)})
60
.send();
61
}
62
63
function _minimizeColumn(e) {
64
e.kill();
65
userMinimize = !userMinimize;
66
JX.DOM.alterClass(document.body, 'minimize-column', userMinimize);
67
JX.Stratcom.invoke('resize');
68
69
if (!userMinimize) {
70
var messages = _getColumnMessagesNode();
71
scrollbar.scrollTo(messages.scrollHeight);
72
}
73
74
new JX.Request(config.minimizeURI)
75
.setData({value: (userMinimize ? 1 : 0)})
76
.send();
77
}
78
79
function _drawColumn(visible) {
80
JX.DOM.alterClass(
81
document.body,
82
'with-durable-column',
83
visible);
84
85
var column = _getColumnNode();
86
if (visible) {
87
JX.DOM.show(column);
88
threadManager.loadThreadByID(loadThreadID);
89
} else {
90
JX.DOM.hide(column);
91
}
92
JX.Quicksand.setFrame(visible ? quick : null);
93
94
JX.Stratcom.invoke('resize');
95
}
96
97
JX.Stratcom.listen(
98
'click',
99
'conpherence-persist-column',
100
_toggleColumn);
101
102
JX.Stratcom.listen(
103
'click',
104
'conpherence-minimize-window',
105
_minimizeColumn);
106
107
scrollbar = new JX.Scrollbar(_getColumnScrollNode());
108
109
JX.Quicksand.setFrame(userVisible ? quick : null);
110
JX.Quicksand.start(config.quicksandConfig);
111
112
/* Conpherence Thread Manager configuration - lots of display
113
* callbacks.
114
*/
115
116
var threadManager = new JX.ConpherenceThreadManager();
117
threadManager.setMessagesRootCallback(function() {
118
return _getColumnMessagesNode();
119
});
120
threadManager.setLoadThreadURI('/conpherence/columnview/');
121
threadManager.setWillLoadThreadCallback(function() {
122
_markLoading(true);
123
});
124
threadManager.setDidLoadThreadCallback(function(r) {
125
var column = _getColumnNode();
126
var new_column = JX.$H(r.content);
127
JX.DOM.replace(column, new_column);
128
if (show) {
129
JX.DOM.show(_getColumnNode());
130
} else {
131
JX.DOM.hide(_getColumnNode());
132
}
133
var messages = _getColumnMessagesNode();
134
scrollbar = new JX.Scrollbar(_getColumnScrollNode());
135
scrollbar.scrollTo(messages.scrollHeight);
136
_markLoading(false);
137
loadThreadID = threadManager.getLoadedThreadID();
138
});
139
threadManager.setDidUpdateThreadCallback(function(r) {
140
var messages = _getColumnMessagesNode();
141
scrollbar.scrollTo(messages.scrollHeight);
142
});
143
144
threadManager.setWillSendMessageCallback(function() {
145
// Wipe the textarea immediately so the user can start typing more text.
146
var textarea = _getColumnTextareaNode();
147
textarea.value = '';
148
_focusColumnTextareaNode();
149
});
150
151
threadManager.setDidSendMessageCallback(function(r, non_update) {
152
if (non_update) {
153
return;
154
}
155
var messages = _getColumnMessagesNode();
156
scrollbar.scrollTo(messages.scrollHeight);
157
});
158
159
threadManager.setWillUpdateWorkflowCallback(function() {
160
JX.Stratcom.invoke('notification-panel-close');
161
});
162
threadManager.setDidUpdateWorkflowCallback(function(r) {
163
var messages = _getColumnMessagesNode();
164
scrollbar.scrollTo(messages.scrollHeight);
165
JX.DOM.setContent(_getColumnTitleNode(), r.conpherence_title);
166
});
167
threadManager.start();
168
169
JX.Stratcom.listen(
170
'click',
171
'conpherence-durable-column-header-action',
172
function (e) {
173
e.kill();
174
var data = e.getNodeData('conpherence-durable-column-header-action');
175
var action = data.action;
176
var link = e.getNode('tag:a');
177
var params = null;
178
179
switch (action) {
180
case 'go_edit':
181
threadManager.runUpdateWorkflowFromLink(
182
link,
183
{
184
action: action,
185
force_ajax: true,
186
stage: 'submit'
187
});
188
break;
189
case 'add_person':
190
threadManager.runUpdateWorkflowFromLink(
191
link,
192
{
193
action: action,
194
stage: 'submit'
195
});
196
break;
197
case 'go_conpherence':
198
JX.$U(link.href).go();
199
break;
200
case 'hide_column':
201
JX.Stratcom.invoke('notification-panel-close');
202
_toggleColumn();
203
break;
204
}
205
});
206
207
JX.Stratcom.listen(
208
'click',
209
'conpherence-durable-column-thread-icon',
210
function (e) {
211
e.kill();
212
var icons = JX.DOM.scry(
213
JX.$('conpherence-durable-column'),
214
'a',
215
'conpherence-durable-column-thread-icon');
216
var data = e.getNodeData('conpherence-durable-column-thread-icon');
217
var cdata = null;
218
for (var i = 0; i < icons.length; i++) {
219
cdata = JX.Stratcom.getData(icons[i]);
220
JX.DOM.alterClass(
221
icons[i],
222
'selected',
223
cdata.threadID == data.threadID);
224
}
225
JX.DOM.setContent(_getColumnTitleNode(), JX.$H(data.threadTitle));
226
threadManager.loadThreadByID(data.threadID);
227
});
228
229
JX.Stratcom.listen('resize', null, _updateColumnVisibility);
230
231
function _getColumnBodyNode() {
232
var column = JX.$('conpherence-durable-column');
233
return JX.DOM.find(
234
column,
235
'div',
236
'conpherence-durable-column-body');
237
}
238
239
function _getColumnMessagesNode() {
240
var column = JX.$('conpherence-durable-column');
241
return JX.DOM.find(
242
column,
243
'div',
244
'conpherence-durable-column-transactions');
245
}
246
247
function _getColumnTitleNode() {
248
var column = JX.$('conpherence-durable-column');
249
return JX.DOM.find(
250
column,
251
'div',
252
'conpherence-durable-column-header-text');
253
}
254
255
function _getColumnFormNode() {
256
var column = JX.$('conpherence-durable-column');
257
return JX.DOM.find(
258
column,
259
'form',
260
'conpherence-message-form');
261
}
262
263
function _getColumnTextareaNode() {
264
var column = JX.$('conpherence-durable-column');
265
return JX.DOM.find(
266
column,
267
'textarea',
268
'conpherence-durable-column-textarea');
269
}
270
271
function _focusColumnTextareaNode() {
272
var textarea = _getColumnTextareaNode();
273
setTimeout(function() { JX.DOM.focus(textarea); }, 1);
274
}
275
276
function _markLoading(loading) {
277
var column = _getColumnNode();
278
JX.DOM.alterClass(column, 'loading', loading);
279
}
280
281
function _sendMessage(e) {
282
e.kill();
283
var form = _getColumnFormNode();
284
threadManager.sendMessage(form, {});
285
}
286
287
JX.Stratcom.listen(
288
'click',
289
'conpherence-send-message',
290
_sendMessage);
291
292
JX.Stratcom.listen(
293
['submit', 'didSyntheticSubmit'],
294
'conpherence-message-form',
295
_sendMessage);
296
297
// Send on enter if the shift key is not held.
298
JX.Stratcom.listen(
299
'keydown',
300
'conpherence-message-form',
301
function(e) {
302
if (e.getSpecialKey() != 'return') {
303
return;
304
}
305
306
var raw = e.getRawEvent();
307
if (raw.shiftKey) {
308
// If the shift key is pressed, let the browser write a newline into
309
// the textarea.
310
return;
311
}
312
313
// From here on, interpret this as a "send" action, not a literal
314
// newline.
315
e.kill();
316
317
_sendMessage(e);
318
});
319
320
JX.Stratcom.listen(
321
['keydown'],
322
'conpherence-durable-column-textarea',
323
function (e) {
324
threadManager.handleDraftKeydown(e);
325
});
326
327
// HTML5 placeholders are rendered as long as the input is empty, even if the
328
// input is currently focused. This is undesirable for the chat input,
329
// especially immediately after sending a message. Hide the placeholder while
330
// the input is focused.
331
JX.Stratcom.listen(
332
['focus', 'blur'],
333
'conpherence-durable-column-textarea',
334
function (e) {
335
var node = e.getTarget();
336
if (e.getType() == 'focus') {
337
if (node.placeholder) {
338
node.placeholderStorage = node.placeholder;
339
node.placeholder = '';
340
}
341
} else {
342
if (node.placeholderStorage) {
343
node.placeholder = node.placeholderStorage;
344
node.placeholderStorage = '';
345
}
346
}
347
});
348
349
JX.Stratcom.listen(
350
'quicksand-redraw',
351
null,
352
function (e) {
353
var new_data = e.getData().newResponse;
354
var new_classes = new_data.bodyClasses;
355
if (userMinimize) {
356
new_classes = new_classes + ' minimize-column';
357
}
358
document.body.className = new_classes;
359
JX.Title.setTitle(new_data.title);
360
});
361
362
_updateColumnVisibility();
363
364
});
365
366