Initial pass on MessageBox rendered with React Infinite and js line wrapping, fix line wrapping bug, disable browser line wrapping

This commit is contained in:
khlieng 2015-02-15 23:27:00 +01:00
parent 3042ed5ec6
commit 6e223c172f
6 changed files with 128 additions and 24 deletions

View File

@ -8,7 +8,8 @@ var messageActions = Reflux.createActions([
'add',
'broadcast',
'inform',
'command'
'command',
'setWrapWidth'
]);
messageActions.send.preEmit = function(message, to, server) {

View File

@ -1,42 +1,70 @@
var React = require('react');
var Reflux = require('reflux');
var _ = require('lodash');
var Infinite = require('react-infinite');
var util = require('../util');
var messageStore = require('../stores/message');
var messageLineStore = require('../stores/messageLine');
var selectedTabStore = require('../stores/selectedTab');
var messageActions = require('../actions/message');
var MessageBox = React.createClass({
mixins: [
Reflux.connect(messageStore, 'messages'),
Reflux.connect(messageLineStore, 'lines'),
Reflux.connect(selectedTabStore, 'selectedTab')
],
getInitialState: function() {
return {
messages: messageStore.getState(),
selectedTab: selectedTabStore.getState()
lines: messageLineStore.getState(),
selectedTab: selectedTabStore.getState(),
height: window.innerHeight - 100
};
},
componentDidMount: function() {
window.addEventListener('resize', this.handleResize);
},
componentWillUnmount: function() {
window.removeEventListener('resize', this.handleResize);
},
componentWillUpdate: function() {
var el = this.getDOMNode();
var el = this.refs.list.getDOMNode();
this.autoScroll = el.scrollTop + el.offsetHeight === el.scrollHeight;
},
componentDidUpdate: function() {
this.updateWidth();
if (this.autoScroll) {
var el = this.getDOMNode();
var el = this.refs.list.getDOMNode();
el.scrollTop = el.scrollHeight;
}
},
handleResize: function() {
this.updateWidth();
this.setState({ height: window.innerHeight - 100 });
},
updateWidth: function() {
var width = this.refs.list.getDOMNode().firstChild.offsetWidth;
if (this.width !== width) {
this.width = width;
messageActions.setWrapWidth(width);
}
},
render: function() {
var tab = this.state.selectedTab;
var dest = tab.channel || tab.server;
var style = {}
var messages = _.map(messageStore.getMessages(tab.server, dest), function(message) {
/*var messages = _.map(messageStore.getMessages(tab.server, dest), function(message) {
var messageClass = 'message';
if (message.type) {
@ -46,18 +74,26 @@ var MessageBox = React.createClass({
return (
<p className={messageClass}>
<span className="message-time">{util.timestamp(message.time)}</span>
{ message.from ? <span className="message-sender">{message.from}</span> : null }
{message.message}
{ message.from ? <span className="message-sender"> {message.from}</span> : null }
{' ' + message.message}
</p>
);
});
});*/
if (!tab.channel || tab.channel[0] !== '#') {
style.right = 0;
}
var lines = _.map(this.state.lines, function(line) {
return <p className="message">{line}</p>;
});
return (
<div className="messagebox" style={style}>{messages}</div>
<div className="messagebox" style={style}>
<Infinite ref="list" containerHeight={this.state.height} elementHeight={24}>
{lines}
</Infinite>
</div>
);
}
});

View File

@ -0,0 +1,63 @@
var Reflux = require('reflux');
var _ = require('lodash');
var util = require('../util');
var messageStore = require('./message');
var selectedTabStore = require('./selectedTab');
var messageActions = require('../actions/message');
var width = window.innerWidth;
var charWidth = util.stringWidth(' ', '16px Ubuntu Mono');
var tab = selectedTabStore.getState();
var messages;
var lines;
wrap();
function wrap() {
messages = messageStore.getMessages(tab.server, tab.channel || tab.server);
lines = util.wrap(_.map(messages, function(message) {
var line = util.timestamp(message.time);
if (message.from) {
line += ' ' + message.from;
}
line += ' ' + message.message;
return line;
}), width, charWidth);
}
var messageLineStore = Reflux.createStore({
init: function() {
this.listenTo(messageActions.setWrapWidth, 'setWrapWidth');
this.listenTo(messageStore, 'messagesChanged');
this.listenTo(selectedTabStore, 'selectedTabChanged');
},
setWrapWidth: function(w) {
width = w;
wrap();
this.trigger(lines);
},
messagesChanged: function() {
wrap();
this.trigger(lines);
},
selectedTabChanged: function(selectedTab) {
tab = selectedTab;
wrap();
this.trigger(lines);
},
getState: function() {
return lines;
}
});
module.exports = messageLineStore;

View File

@ -55,8 +55,8 @@ var selectedTabStore = Reflux.createStore({
userAdded: function(user, server, channel) {
// Update the selected channel incase the casing is different
if (server === selectedTab.server &&
channel.toLowerCase() === selectedTab.channel.toLowerCase() &&
user === serverStore.getNick(server)) {
user === serverStore.getNick(server) &&
channel.toLowerCase() === selectedTab.channel.toLowerCase()) {
selectedTab.channel = channel;
selectedTab.name = channel;
this.trigger(selectedTab);

View File

@ -37,13 +37,12 @@ exports.wrap = function(lines, width, charWidth) {
if (wordCount !== 1) {
wrapped.push(line);
line = word;
lineWidth = word.length * charWidth;
wordCount = 1;
if (i !== wlen - 1) {
line += ' ';
lineWidth += charWidth;
line = word + ' ';
lineWidth = (word.length + 1) * charWidth;
wordCount = 1;
} else {
wrapped.push(word);
}
} else {
wrapped.push(word);

View File

@ -207,19 +207,24 @@ p {
top: 50px;
bottom: 50px;
right: 200px;
padding: 15px;
overflow: auto;
/*padding: 15px;*/
z-index: 1;
}
.messagebox > div {
padding: 10px 15px;
overflow: auto !important;
}
.message {
margin-bottom: 5px;
white-space: nowrap;
/*margin-bottom: 5px;
padding-left: 55px;
text-indent: -55px;
text-indent: -55px;*/
}
.message span {
margin-right: 15px;
/*margin-right: 15px;*/
}
.message-info {