Immutable channelStore

This commit is contained in:
Ken-Håvard Lieng 2015-05-19 06:50:43 +02:00
parent 11ea241b60
commit 17482ee253
9 changed files with 116 additions and 143 deletions

View File

@ -52,7 +52,7 @@ var Chat = React.createClass({
<div className={chatClass}>
<ChatTitle />
<Search />
<MessageBox indent={window.messageIndent} />
<MessageBox />
<MessageInput />
<UserList />
</div>

View File

@ -18,7 +18,7 @@ var ChatTitle = React.createClass({
var tab = selectedTabStore.getState();
return {
usercount: channelStore.getUsers(tab.server, tab.channel).length,
usercount: channelStore.getUsers(tab.server, tab.channel).size,
selectedTab: tab
};
},
@ -26,13 +26,13 @@ var ChatTitle = React.createClass({
channelsChanged() {
var tab = this.state.selectedTab;
this.setState({ usercount: channelStore.getUsers(tab.server, tab.channel).length });
this.setState({ usercount: channelStore.getUsers(tab.server, tab.channel).size });
},
selectedTabChanged(tab) {
this.setState({
selectedTab: tab,
usercount: channelStore.getUsers(tab.server, tab.channel).length
usercount: channelStore.getUsers(tab.server, tab.channel).size
});
},

View File

@ -66,9 +66,6 @@ var MessageBox = React.createClass({
var tab = this.state.selectedTab;
var dest = tab.channel || tab.server;
var lines = [];
var innerStyle = {
paddingLeft: this.props.indent + 'px'
};
this.state.messages.forEach((message, j) => {
var key = message.server + dest + j;

View File

@ -32,8 +32,8 @@ var TabList = React.createClass({
},
render() {
var tabs = _.map(this.state.channels, (server, address) => {
var serverTabs = _.map(server, (channel, name) => {
var tabs = this.state.channels.map((server, address) => {
var serverTabs = server.map((channel, name) => {
return (
<TabListItem
server={address}
@ -41,7 +41,7 @@ var TabList = React.createClass({
name={name}>
</TabListItem>
);
});
}).toArray();
_.each(this.state.privateChats[address], (chat, nick) => {
serverTabs.push(

View File

@ -56,9 +56,9 @@ var UserList = React.createClass({
if (!tab.channel || tab.channel[0] !== '#') {
style.display = 'none';
} else {
users = _.map(this.state.users, (user) => {
users = this.state.users.map(user => {
return <UserListItem key={user.nick} user={user} />;
});
}).toArray(); // React Infinite uses .length
}
if (users.length !== 1) {

View File

@ -1,29 +1,28 @@
var Reflux = require('reflux');
var Immutable = require('immutable');
var _ = require('lodash');
var actions = require('../actions/channel');
var serverActions = require('../actions/server');
var channels = {};
var channels = Immutable.Map();
var empty = Immutable.List();
function initChannel(server, channel) {
if (!(server in channels)) {
channels[server] = {};
channels[server][channel] = { users: [] };
} else if (!(channel in channels[server])) {
channels[server][channel] = { users: [] };
}
}
var User = Immutable.Record({
nick: null,
renderName: null,
mode: ''
});
function createUser(nick, mode) {
return updateRenderName({
return updateRenderName(new User({
nick: nick,
renderName: nick,
mode: mode || ''
});
}));
}
function loadUser(users, nick) {
function loadUser(nick) {
var mode;
if (nick[0] === '@') {
@ -36,46 +35,42 @@ function loadUser(users, nick) {
nick = nick.slice(1);
}
users.push(createUser(nick, mode));
return createUser(nick, mode);
}
function updateRenderName(user) {
if (user.mode.indexOf('o') !== -1) {
user.renderName = '@' + user.nick;
return user.set('renderName', '@' + user.nick);
} else if (user.mode.indexOf('v') !== -1) {
user.renderName = '+' + user.nick;
return user.set('renderName', '+' + user.nick);
} else {
user.renderName = user.nick;
return user.set('renderName', user.nick);
}
return user;
}
function sortUsers(server, channel) {
channels[server][channel].users.sort(function(a, b) {
a = a.renderName.toLowerCase();
b = b.renderName.toLowerCase();
function sortUsers(a, b) {
a = a.renderName.toLowerCase();
b = b.renderName.toLowerCase();
if (a[0] === '@' && b[0] !== '@') {
return -1;
}
if (b[0] === '@' && a[0] !== '@') {
return 1;
}
if (a[0] === '+' && b[0] !== '+') {
return -1;
}
if (b[0] === '+' && a[0] !== '+') {
return 1;
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
if (a[0] === '@' && b[0] !== '@') {
return -1;
}
if (b[0] === '@' && a[0] !== '@') {
return 1;
}
if (a[0] === '+' && b[0] !== '+') {
return -1;
}
if (b[0] === '+' && a[0] !== '+') {
return 1;
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
var channelStore = Reflux.createStore({
@ -88,134 +83,112 @@ var channelStore = Reflux.createStore({
part(partChannels, server) {
_.each(partChannels, function(channel) {
delete channels[server][channel];
channels = channels.deleteIn([server, channel]);
});
this.trigger(channels);
},
addUser(user, server, channel) {
initChannel(server, channel);
channels[server][channel].users.push(createUser(user));
sortUsers(server, channel);
channels = channels.updateIn([server, channel, 'users'], empty, users => {
return users.push(createUser(user)).sort(sortUsers);
});
this.trigger(channels);
},
removeUser(user, server, channel) {
if (channels[server][channel]) {
_.remove(channels[server][channel].users, { nick: user });
if (channels.hasIn([server, channel])) {
channels = channels.updateIn([server, channel, 'users'], users => users.filter(u => u.nick !== user));
this.trigger(channels);
}
},
removeUserAll(user, server) {
_.each(channels[server], function(channel) {
_.remove(channel.users, { nick: user });
channels.get(server).forEach((v, k) => {
channels = channels.updateIn([server, k, 'users'], users => users.filter(u => u.nick !== user));
});
this.trigger(channels);
},
renameUser(oldNick, newNick, server) {
_.each(channels[server], function(channel, channelName) {
var user = _.find(channel.users, { nick: oldNick });
if (user) {
user.nick = newNick;
updateRenderName(user);
sortUsers(server, channelName);
}
channels.get(server).forEach((v, k) => {
channels = channels.updateIn([server, k, 'users'], users => {
var i = users.findIndex(user => user.nick === oldNick);
return users.update(i, user => {
return updateRenderName(user.set('nick', newNick));
}).sort(sortUsers);
});
});
this.trigger(channels);
},
setUsers(users, server, channel) {
initChannel(server, channel);
var chan = channels[server][channel];
chan.users = [];
_.each(users, function(user) {
loadUser(chan.users, user);
});
sortUsers(server, channel);
users = _.map(users, user => loadUser(user)).sort(sortUsers);
channels = channels.setIn([server, channel, 'users'], Immutable.List(users));
this.trigger(channels);
},
setTopic(topic, server, channel) {
channels[server][channel].topic = topic;
channels = channels.setIn([server, channel, 'topic'], topic);
this.trigger(channels);
},
setMode(mode) {
var user = _.find(channels[mode.server][mode.channel].users, { nick: mode.user });
if (user) {
_.each(mode.remove, function(mode) {
user.mode = user.mode.replace(mode, '');
});
_.each(mode.add, function(mode) {
user.mode += mode;
});
var i = channels.getIn([mode.server, mode.channel, 'users']).findIndex(u => u.nick === mode.user);
updateRenderName(user);
sortUsers(mode.server, mode.channel);
this.trigger(channels);
}
channels = channels.updateIn([mode.server, mode.channel, 'users', i], user => {
_.each(mode.remove, function(mode) {
user = user.set('mode', user.mode.replace(mode, ''));
});
user = user.set('mode', user.mode + mode.add);
return updateRenderName(user);
});
channels = channels.updateIn([mode.server, mode.channel, 'users'], users => users.sort(sortUsers));
this.trigger(channels);
},
load(storedChannels) {
_.each(storedChannels, function(channel) {
initChannel(channel.server, channel.name);
var chan = channels[channel.server][channel.name];
chan.users = [];
chan.topic = channel.topic;
_.each(channel.users, function(user) {
loadUser(chan.users, user);
});
sortUsers(channel.server, channel.name);
channels = channels.setIn([channel.server, channel.name], Immutable.Map({
users: Immutable.List(),
topic: channel.topic
}));
});
this.trigger(channels);
},
addServer(server) {
if (!(server in channels)) {
channels[server] = {};
if (!channels.has(server)) {
channels = channels.set(server, Immutable.Map());
this.trigger(channels);
}
},
removeServer(server) {
delete channels[server];
channels = channels.delete(server);
this.trigger(channels);
},
loadServers(storedServers) {
_.each(storedServers, function(server) {
if (!(server.address in channels)) {
channels[server.address] = {};
if (!channels.has(server.address)) {
channels = channels.set(server.address, Immutable.Map());
}
});
this.trigger(channels);
},
getChannels(server) {
return channels[server];
return channels.get(server);
},
getUsers(server, channel) {
if (channels[server] && channels[server][channel]) {
return channels[server][channel].users;
}
return [];
return channels.getIn([server, channel, 'users']) || empty;
},
getTopic(server, channel) {
if (channels[server] && channels[server][channel]) {
return channels[server][channel].topic || null;
}
return null;
return channels.getIn([server, channel, 'topic']) || null;
},
getState() {

View File

@ -63,8 +63,8 @@ var messageStore = Reflux.createStore({
},
broadcast(message, server, user) {
_.each(channelStore.getChannels(server), function(channel, channelName) {
if (!user || (user && _.find(channel.users, { nick: user }))) {
channelStore.getChannels(server).forEach((channel, channelName) => {
if (!user || (user && channel.get('users').find(u => u.nick === user))) {
addMessage({
server: server,
to: channelName,

View File

@ -6,17 +6,16 @@ var messageStore = require('./message');
var selectedTabStore = require('./selectedTab');
var messageActions = require('../actions/message');
var width = window.innerWidth;
window.charWidth = util.stringWidth(' ', '16px Droid Sans Mono');
window.messageIndent = 6 * charWidth;
// Temporary hack incase this runs before the font has loaded
setTimeout(() => window.charWidth = util.stringWidth(' ', '16px Droid Sans Mono'), 1000);
var tab = selectedTabStore.getState();
var width = window.innerWidth;
var messages;
var prev;
function updateCharWidth() {
window.charWidth = util.stringWidth(' ', '16px Droid Sans Mono');
window.messageIndent = 6 * charWidth;
}
function wrap() {
var next = messageStore.getMessages(tab.server, tab.channel || tab.server);
if (next !== prev) {
@ -27,10 +26,14 @@ function wrap() {
return false;
}
wrap();
var messageLineStore = Reflux.createStore({
init() {
updateCharWidth();
wrap();
// Temporary hack incase this runs before the font has loaded
setTimeout(updateCharWidth, 1000);
this.listenTo(messageActions.setWrapWidth, 'setWrapWidth');
this.listenTo(messageStore, 'messagesChanged');
this.listenTo(selectedTabStore, 'selectedTabChanged');

File diff suppressed because one or more lines are too long