"params": params
};
window.ws_conn.send(JSON.stringify(m));
+ },
+ handle_msg: function(obj) {
+ console.log(obj);
+ if (obj.sender == "blist") {
+ this.handle_blist_message(obj.method, obj.params);
+ } else if (obj.sender == "conversations") {
+ this.handle_conversations_message(obj.method, obj.params);
+ }
+ },
+ handle_blist_message: function(method, params) {
+ bid = params.proto + ":" + params.account + ":" + params.buddy;
+ // Create buddy entry in blist if none exists yet
+ if (window.blist[bid] === undefined) {
+ window.blist[bid] = {
+ proto: params.proto,
+ account: params.account,
+ buddy: params.buddy,
+ status: {}
+ };
+ }
+ if (method == "buddy_status_changed") {
+ window.blist[bid].status = params.status;
+ } else if (method == "buddy_icon_changed") {
+ window.blist[bid].bicon_url = params.url;
+ }
+ window.buddy_list.onChange(window.blist);
+ },
+ handle_conversations_message: function(method, params) {
+ console.log("conversations:", method, params);
+ bid = params.proto + ":" + params.account + ":" + params.buddy;
+ if (window.conversations[bid] === undefined) {
+ window.conversations[bid] = {
+ proto: params.proto,
+ account: params.account,
+ buddy: params.buddy,
+ messages: [],
+ visible: false,
+ type_state: "stopped"
+ };
+ }
+
+ if (method == "recv_im") {
+ window.conversations[bid].visible = true;
+ window.conversations[bid].messages.push({
+ message: params.message,
+ timestamp: params.timestamp,
+ sender: "them"
+ });
+ } else if (method == "buddy_typing_state") {
+ window.conversations[bid].type_state = params.state;
+ }
+ // TODO: repaint conversations window
}
};
<!-- A div for the initial login form -->
<div id="loginform"></div>
<!-- A div for the buddy list -->
- <div id="blist"></div>
+ <div id="buddy_list"></div>
<!-- A div for the tabbed chat view -->
<div id="chats"></div>
</body>
// this is like a main.js
-window.blist = {}
+window.blist = {} // buid -> {proto, account, buddy, status, bicon_url }
+window.conversations = {} // buid -> {proto, account, buddy, messages[], visible, type_state }
window.onload = function () {
// Create websocket and attach to window
ws.onmessage = function(evt) {
//console.log("message received: " + evt.data);
var message = JSON.parse(evt.data)
- console.log(message);
+ window.Dispatcher.handle_msg(message);
};
ws.onclose = function(evt) {
console.log("connection closed");
document.getElementById('loginform')
);
- window.blist = React.renderComponent(
+ window.buddy_list = React.renderComponent(
window.widgets.BuddyList(),
- document.getElementById('blist')
+ document.getElementById('buddy_list')
);
console.log("loaded");
};
(r'/(index.html)', tornado.web.StaticFileHandler, {'path': pwd}),
(r'/([a-z]*\.js)', tornado.web.StaticFileHandler, {'path': pwd}),
(r'/([a-z]*\.css)', tornado.web.StaticFileHandler, {'path': pwd}),
+ (r'/icons/(.*)', tornado.web.StaticFileHandler, {'path': os.path.join(pwd, 'state', 'icons')}),
(r'/ws', WSHandler),
])
if __name__ == "__main__":
# Spawn the ribbon subprocess
ribbon_binary = os.path.join(os.path.dirname(pwd), "ribbon", "ribbon")
- ribbon = subprocess.Popen( [ribbon_binary], close_fds=True )
+ ribbon = subprocess.Popen( [ribbon_binary, "--state-dir", os.path.join(pwd, "state")], close_fds=True )
# Spawn the http server
http_server = tornado.httpserver.HTTPServer(application)
+body {
+ margin: 0px;
+ padding: 0px;
+ min-height: 100vh;
+}
+
.form {
float: left;
}
margin-bottom: 20px;
}
-#blist {
+#buddy_list {
float: right;
}
/* buddy list things */
-.blistitem {
+.buddy {
width: 200px;
height: 48px;
font-size: small;
}
-.blistitem > img {
+.buddy > img {
display: inline-block;
width: 48px;
height: 48px;
float: left;
}
-.blistitemcontainer {
+.buddycontainer {
display: inline-block;
vertical-align: top;
width: 152px;
}
-.blist-buddyname {
+.buddyname {
font-weight: bold;
}
-.blisttext {
+.buddytext {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
},
handleLogin: function () {
console.log("Imma log in now");
- command = {
- "destination": "accounts",
- "method": "create_account",
- "params": this.state
- };
- window.ws_conn.send(JSON.stringify(command));
+ window.Dispatcher.send_msg("accounts", "create_account", this.state);
},
render: function () {
var BuddyListItem = React.createClass({
render: function () {
- return <div className="blistitem">
+ return <div className="buddy">
<img className="buddyicon" src={this.props.bicon_url} />
- <div className="blistitemcontainer">
- <div className="blist-buddyname blisttext">{this.props.display_name}</div>
- <div className="blisttext">{this.props.status}</div>
+ <div className="buddycontainer">
+ <div className="buddyname buddytext">{this.props.display_name}</div>
+ <div className="buddytext">{this.props.status_msg}</div>
</div>
</div>;
}
return {"buddies": []};
},
onChange: function(newData) {
- this.setState( { "buddies": newData } );
+ // parse out newData and convert to structure expected by widget
+ var buddy_ids = Object.keys(newData);
+ buddy_ids.sort();
+ var buddies = [];
+ for (var i = 0 ; i < buddy_ids.length ; i++) {
+ var buddy = newData[buddy_ids[i]];
+ buddies.push({
+ bicon_url: buddy.bicon_url,
+ display_name: buddy.buddy,
+ status_msg: buddy.status.status_msg
+ });
+ }
+ this.setState( { "buddies": buddies } );
},
render: function () {
// for each thing in this.state:
var s = this.state.buddies[i];
things.push(BuddyListItem(this.state.buddies[i]));
}
- return <div className="blist">{ things }</div>;
+ return <div className="buddy_list">{ things }</div>;
}
});