1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 17:02:41 +01:00
phorge-phorge/webroot/rsrc/js/application/conpherence/ConpherenceThreadManager.js
Bob Trahan 2373185e9b Conpherence - introduce ConpherenceThreadManager
Summary:
Ref T7014. Fixes T7473. This adds a class to handle thread state about what thread is loaded and what transaction we've seen last. It is deployed 100% in the durable column and only partially deployed in the regular view. Future diff(s) should clean up regular view. Note ConpherenceThreadManager API might change a bit at that time.

Also includes a bonus bug fix so logged out users can't toggle this column

Test Plan: tried to use durable column while logged out and nothing happened. sent messages, aphlict-received messages, added people, and changed title from both views

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T7473, T7014

Differential Revision: https://secure.phabricator.com/D12029
2015-03-10 12:20:29 -07:00

271 lines
7.2 KiB
JavaScript

/**
* @provides conpherence-thread-manager
* @requires javelin-dom
* javelin-util
* javelin-stratcom
* javelin-install
* javelin-workflow
* javelin-router
* javelin-behavior-device
* javelin-vector
*/
JX.install('ConpherenceThreadManager', {
construct : function() {
if (__DEV__) {
if (JX.ConpherenceThreadManager._instance) {
JX.$E('ConpherenceThreadManager object is a singleton.');
}
}
JX.ConpherenceThreadManager._instance = this;
return this;
},
members: {
_loadThreadURI: null,
_loadedThreadID: null,
_loadedThreadPHID: null,
_latestTransactionID: null,
_updating: null,
_minimalDisplay: false,
_getMessagesNodeFunction: JX.bag,
_getTitleNodeFunction: JX.bag,
_willLoadThreadCallback: JX.bag,
_didLoadThreadCallback: JX.bag,
_willSendMessageCallback: JX.bag,
_didSendMessageCallback: JX.bag,
setLoadThreadURI: function(uri) {
this._loadThreadURI = uri;
return this;
},
getLoadThreadURI: function() {
return this._loadThreadURI;
},
isThreadLoaded: function() {
return Boolean(this._loadedThreadID);
},
isThreadIDLoaded: function(thread_id) {
return this._loadedThreadID == thread_id;
},
getLoadedThreadID: function() {
return this._loadedThreadID;
},
getLoadedThreadPHID: function() {
return this._loadedThreadPHID;
},
getLatestTransactionID: function() {
return this._latestTransactionID;
},
setLatestTransactionID: function(id) {
this._latestTransactionID = id;
return this;
},
setMessagesNodeFunction: function(callback) {
this._getMessagesNodeFunction = callback;
return this;
},
_getMessagesNode: function() {
return this._getMessagesNodeFunction();
},
setTitleNodeFunction: function(callback) {
this._getTitleNodeFunction = callback;
return this;
},
_getTitleNode: function() {
return this._getTitleNodeFunction();
},
setMinimalDisplay: function(bool) {
this._minimalDisplay = bool;
return this;
},
setWillLoadThreadCallback: function(callback) {
this._willLoadThreadCallback = callback;
return this;
},
setDidLoadThreadCallback: function(callback) {
this._didLoadThreadCallback = callback;
return this;
},
setWillSendMessageCallback: function(callback) {
this._willSendMessageCallback = callback;
return this;
},
setDidSendMessageCallback: function(callback) {
this._didSendMessageCallback = callback;
return this;
},
_getParams: function(base_params) {
if (this._minimalDisplay) {
base_params.minimal_display = true;
}
if (this._latestTransactionID) {
base_params.latest_transaction_id = this._latestTransactionID;
}
return base_params;
},
start: function() {
JX.Stratcom.listen(
'aphlict-server-message',
null,
JX.bind(this, function(e) {
var message = e.getData();
if (message.type != 'message') {
// Not a message event.
return;
}
if (message.threadPHID != this._loadedThreadPHID) {
// Message event for some thread other than the visible one.
return;
}
if (message.messageID <= this._latestTransactionID) {
// Message event for something we already know about.
return;
}
// If we're currently updating, wait for the update to complete.
// If this notification tells us about a message which is newer than
// the newest one we know to exist, keep track of it so we can
// update once the in-flight update finishes.
if (this._updating &&
this._updating.threadPHID == this._loadedThreadPHID) {
if (message.messageID > this._updating.knownID) {
this._updating.knownID = message.messageID;
return;
}
}
this._updateThread();
}));
},
_updateThread: function() {
var params = this._getParams({
action: 'load',
});
var uri = '/conpherence/update/' + this._loadedThreadID + '/';
var workflow = new JX.Workflow(uri)
.setData(params)
.setHandler(JX.bind(this, function(r) {
this._latestTransactionID = r.latest_transaction_id;
var messages = this._getMessagesNode();
JX.DOM.appendContent(messages, JX.$H(r.transactions));
messages.scrollTop = messages.scrollHeight;
}));
this.syncWorkflow(workflow, 'finally');
},
syncWorkflow: function(workflow, stage) {
this._updating = {
threadPHID: this._loadedThreadPHID,
knownID: this._latestTransactionID
};
workflow.listen(stage, JX.bind(this, function() {
// TODO - do we need to handle if we switch threads somehow?
var need_sync = (this._updating.knownID > this._latestTransactionID);
this._updating = null;
if (need_sync) {
this._updateThread();
}
}));
workflow.start();
},
runUpdateWorkflowFromLink: function(link, params) {
params = this._getParams(params);
var workflow = new JX.Workflow.newFromLink(link)
.setData(params)
.setHandler(JX.bind(this, function(r) {
this._latestTransactionID = r.latest_transaction_id;
var messages = this._getMessagesNode();
JX.DOM.appendContent(messages, JX.$H(r.transactions));
messages.scrollTop = messages.scrollHeight;
JX.DOM.setContent(this._getTitleNode(), r.conpherence_title);
}));
this.syncWorkflow(workflow, params.stage);
},
loadThreadByID: function(thread_id) {
if (this.isThreadLoaded() &&
this.isThreadIDLoaded(thread_id)) {
return;
}
this._willLoadThreadCallback();
var params = {};
// We pick a thread from the server if not specified
if (thread_id) {
params.id = thread_id;
}
params = this._getParams(params);
var handler = JX.bind(this, function(r) {
this._loadedThreadID = r.threadID;
this._loadedThreadPHID = r.threadPHID;
this._loadThreadID = r.threadID;
this._latestTransactionID = r.latestTransactionID;
this._didLoadThreadCallback(r);
});
// should this be sync'd too?
new JX.Workflow(this.getLoadThreadURI())
.setData(params)
.setHandler(handler)
.start();
},
sendMessage: function(form, params) {
params = this._getParams(params);
this._willSendMessageCallback();
var workflow = JX.Workflow.newFromForm(form, params)
.setHandler(JX.bind(this, function(r) {
this._latestTransactionID = r.latest_transaction_id;
this._didSendMessageCallback(r);
}));
this.syncWorkflow(workflow, 'finally');
}
},
statics: {
_instance: null,
getInstance: function() {
var self = JX.ConpherenceThreadManager;
if (!self._instance) {
return null;
}
return self._instance;
}
}
});