Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/application/conpherence/behavior-pontificate.js
| /** | /** | ||||
| * @provides javelin-behavior-conpherence-pontificate | * @provides javelin-behavior-conpherence-pontificate | ||||
| * @requires javelin-behavior | * @requires javelin-behavior | ||||
| * javelin-dom | * javelin-dom | ||||
| * javelin-util | * javelin-util | ||||
| * javelin-workflow | * javelin-workflow | ||||
| * javelin-stratcom | * javelin-stratcom | ||||
| */ | */ | ||||
| JX.behavior('conpherence-pontificate', function() { | JX.behavior('conpherence-pontificate', function() { | ||||
| // TODO: This isn't very clean. When you submit a message, you may get a | |||||
| // notification about it back before you get the rendered message back. To | |||||
| // prevent this, we keep track of whether we're currently updating the | |||||
| // thread. If we are, we hold further updates until the response comes | |||||
| // back. | |||||
| // After the response returns, we'll do another update if we know about | |||||
| // a transaction newer than the one we got back from the server. | |||||
| var updating = null; | |||||
| function get_thread_data() { | |||||
| // TODO: This is really, really gross. | |||||
| var infonode = JX.DOM.find(document, 'input', 'latest-transaction-id'); | |||||
| var data = JX.Stratcom.getData(infonode); | |||||
| data.latestID = infonode.value; | |||||
| return data; | |||||
| } | |||||
| function update_latest_transaction_id(id) { | |||||
| // TODO: Continued grossness from above. | |||||
| var infonode = JX.DOM.find(document, 'input', 'latest-transaction-id'); | |||||
| infonode.value = id; | |||||
| } | |||||
| JX.Stratcom.listen('aphlict-receive-message', null, function(e) { | JX.Stratcom.listen('aphlict-receive-message', null, function(e) { | ||||
| var message = e.getData(); | var message = e.getData(); | ||||
| if (message.type != 'message') { | if (message.type != 'message') { | ||||
| // Not a message event. | // Not a message event. | ||||
| return; | return; | ||||
| } | } | ||||
| // TODO: This is really, really gross. | var data = get_thread_data(); | ||||
| var infonode = JX.DOM.find(document, 'input', 'latest-transaction-id'); | |||||
| var data = JX.Stratcom.getData(infonode); | |||||
| var latest_id = infonode.value; | |||||
| var thread_phid = data.threadPHID; | |||||
| var thread_id = data.threadID; | |||||
| if (message.threadPHID != thread_phid) { | if (message.threadPHID != data.threadPHID) { | ||||
| // Message event for some thread other than the visible one. | // Message event for some thread other than the visible one. | ||||
| return; | return; | ||||
| } | } | ||||
| if (message.messageID <= latest_id) { | if (message.messageID <= data.latestID) { | ||||
| // Message event for something we already know about. | // Message event for something we already know about. | ||||
| return; | 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 (updating && updating.threadPHID == data.threadPHID) { | |||||
| if (message.messageID > updating.knownID) { | |||||
| updating.knownID = message.messageID; | |||||
| return; | |||||
| } | |||||
| } | |||||
| update_thread(data); | |||||
| }); | |||||
| function update_thread(data) { | |||||
| var params = { | var params = { | ||||
| action: 'load', | action: 'load', | ||||
| latest_transaction_id: latest_id | latest_transaction_id: data.latestID | ||||
| }; | }; | ||||
| new JX.Workflow('/conpherence/update/' + thread_id + '/') | var uri = '/conpherence/update/' + data.threadID + '/'; | ||||
| var workflow = new JX.Workflow(uri) | |||||
| .setData(params) | .setData(params) | ||||
| .setHandler(function(r) { | .setHandler(function(r) { | ||||
| var messages = JX.DOM.find(document, 'div', 'conpherence-messages'); | var messages = JX.DOM.find(document, 'div', 'conpherence-messages'); | ||||
| JX.DOM.appendContent(messages, JX.$H(r.transactions)); | JX.DOM.appendContent(messages, JX.$H(r.transactions)); | ||||
| messages.scrollTop = messages.scrollHeight; | messages.scrollTop = messages.scrollHeight; | ||||
| // TODO: Continued grossness from above. | update_latest_transaction_id(r.latest_transaction_id); | ||||
| infonode.value = r.latest_transaction_id; | }); | ||||
| }) | |||||
| .start(); | sync_workflow(workflow, data); | ||||
| } | |||||
| function sync_workflow(workflow, data) { | |||||
| updating = { | |||||
| threadPHID: data.threadPHID, | |||||
| knownID: data.latestID | |||||
| }; | |||||
| workflow.listen('finally', function() { | |||||
| var new_data = get_thread_data(); | |||||
| var need_sync = (updating.knownID > new_data.latestID); | |||||
| updating = null; | |||||
| if (need_sync) { | |||||
| update_thread(new_data); | |||||
| } | |||||
| }); | }); | ||||
| workflow.start(); | |||||
| } | |||||
| var onsubmit = function(e) { | var onsubmit = function(e) { | ||||
| e.kill(); | e.kill(); | ||||
| var form = e.getNode('tag:form'); | var form = e.getNode('tag:form'); | ||||
| var root = e.getNode('conpherence-layout'); | var root = e.getNode('conpherence-layout'); | ||||
| var messages_root = JX.DOM.find(root, 'div', 'conpherence-message-pane'); | var messages_root = JX.DOM.find(root, 'div', 'conpherence-message-pane'); | ||||
| var form_root = JX.DOM.find(root, 'div', 'conpherence-form'); | var form_root = JX.DOM.find(root, 'div', 'conpherence-form'); | ||||
| var messages = JX.DOM.find(messages_root, 'div', 'conpherence-messages'); | var messages = JX.DOM.find(messages_root, 'div', 'conpherence-messages'); | ||||
| var fileWidget = null; | var fileWidget = null; | ||||
| try { | try { | ||||
| fileWidget = JX.DOM.find(root, 'div', 'widgets-files'); | fileWidget = JX.DOM.find(root, 'div', 'widgets-files'); | ||||
| } catch (ex) { | } catch (ex) { | ||||
| // Ignore; maybe no files widget | // Ignore; maybe no files widget | ||||
| } | } | ||||
| JX.DOM.alterClass(form_root, 'loading', true); | JX.DOM.alterClass(form_root, 'loading', true); | ||||
| JX.Workflow.newFromForm(form) | var workflow = JX.Workflow.newFromForm(form) | ||||
| .setHandler(JX.bind(this, function(r) { | .setHandler(JX.bind(this, function(r) { | ||||
| JX.DOM.appendContent(messages, JX.$H(r.transactions)); | JX.DOM.appendContent(messages, JX.$H(r.transactions)); | ||||
| messages.scrollTop = messages.scrollHeight; | messages.scrollTop = messages.scrollHeight; | ||||
| if (fileWidget) { | if (fileWidget) { | ||||
| JX.DOM.setContent( | JX.DOM.setContent( | ||||
| fileWidget, | fileWidget, | ||||
| JX.$H(r.file_widget) | JX.$H(r.file_widget) | ||||
| ); | ); | ||||
| } | } | ||||
| var latest_transaction_dom = JX.DOM.find( | update_latest_transaction_id(r.latest_transaction_id); | ||||
| root, | |||||
| 'input', | |||||
| 'latest-transaction-id'); | |||||
| latest_transaction_dom.value = r.latest_transaction_id; | |||||
| var textarea = JX.DOM.find(form, 'textarea'); | var textarea = JX.DOM.find(form, 'textarea'); | ||||
| textarea.value = ''; | textarea.value = ''; | ||||
| JX.Stratcom.invoke( | JX.Stratcom.invoke( | ||||
| 'conpherence-selectthread', | 'conpherence-selectthread', | ||||
| null, | null, | ||||
| { id : r.conpherence_phid + '-nav-item' } | { id : r.conpherence_phid + '-nav-item' } | ||||
| ); | ); | ||||
| JX.DOM.alterClass(form_root, 'loading', false); | JX.DOM.alterClass(form_root, 'loading', false); | ||||
| })) | })); | ||||
| .start(); | |||||
| sync_workflow(workflow, get_thread_data()); | |||||
| }; | }; | ||||
| JX.Stratcom.listen( | JX.Stratcom.listen( | ||||
| ['submit', 'didSyntheticSubmit'], | ['submit', 'didSyntheticSubmit'], | ||||
| 'conpherence-pontificate', | 'conpherence-pontificate', | ||||
| onsubmit); | onsubmit); | ||||
| }); | }); | ||||