forked from CringeStudios/gamja
Multiple clients per app
This commit is contained in:
parent
95daea0ef7
commit
2f70256037
20
commands.js
20
commands.js
@ -1,5 +1,13 @@
|
|||||||
import { SERVER_BUFFER } from "/state.js";
|
import { SERVER_BUFFER } from "/state.js";
|
||||||
|
|
||||||
|
function getActiveClient(app) {
|
||||||
|
var buf = app.state.buffers.get(app.state.activeBuffer);
|
||||||
|
if (!buf) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return app.clients.get(buf.network);
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
"query": (app, args) => {
|
"query": (app, args) => {
|
||||||
var nick = args[0];
|
var nick = args[0];
|
||||||
@ -33,7 +41,7 @@ export default {
|
|||||||
if (!channel) {
|
if (!channel) {
|
||||||
throw new Error("Missing channel name");
|
throw new Error("Missing channel name");
|
||||||
}
|
}
|
||||||
app.client.send({ command: "JOIN", params: [channel] });
|
getActiveClient(app).send({ command: "JOIN", params: [channel] });
|
||||||
},
|
},
|
||||||
"part": (app, args) => {
|
"part": (app, args) => {
|
||||||
var reason = args.join(" ");
|
var reason = args.join(" ");
|
||||||
@ -45,12 +53,12 @@ export default {
|
|||||||
if (reason) {
|
if (reason) {
|
||||||
params.push(reason);
|
params.push(reason);
|
||||||
}
|
}
|
||||||
app.client.send({ command: "PART", params });
|
getActiveClient(app).send({ command: "PART", params });
|
||||||
},
|
},
|
||||||
"msg": (app, args) => {
|
"msg": (app, args) => {
|
||||||
var target = args[0];
|
var target = args[0];
|
||||||
var text = args.slice(1).join(" ");
|
var text = args.slice(1).join(" ");
|
||||||
app.client.send({ command: "PRIVMSG", params: [target, text] });
|
getActiveClient(app).send({ command: "PRIVMSG", params: [target, text] });
|
||||||
},
|
},
|
||||||
"me": (app, args) => {
|
"me": (app, args) => {
|
||||||
var action = args.join(" ");
|
var action = args.join(" ");
|
||||||
@ -63,12 +71,12 @@ export default {
|
|||||||
},
|
},
|
||||||
"nick": (app, args) => {
|
"nick": (app, args) => {
|
||||||
var newNick = args[0];
|
var newNick = args[0];
|
||||||
app.client.send({ command: "NICK", params: [newNick] });
|
getActiveClient(app).send({ command: "NICK", params: [newNick] });
|
||||||
},
|
},
|
||||||
"notice": (app, args) => {
|
"notice": (app, args) => {
|
||||||
var target = args[0];
|
var target = args[0];
|
||||||
var text = args.slice(1).join(" ");
|
var text = args.slice(1).join(" ");
|
||||||
app.client.send({ command: "NOTICE", params: [target, text] });
|
getActiveClient(app).send({ command: "NOTICE", params: [target, text] });
|
||||||
},
|
},
|
||||||
"buffer": (app, args) => {
|
"buffer": (app, args) => {
|
||||||
var name = args[0];
|
var name = args[0];
|
||||||
@ -89,7 +97,7 @@ export default {
|
|||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
params.push(args.join(" "));
|
params.push(args.join(" "));
|
||||||
}
|
}
|
||||||
app.client.send({ command: "TOPIC", params });
|
getActiveClient(app).send({ command: "TOPIC", params });
|
||||||
},
|
},
|
||||||
"reconnect": (app, args) => {
|
"reconnect": (app, args) => {
|
||||||
app.reconnect();
|
app.reconnect();
|
||||||
|
@ -139,7 +139,6 @@ function getBuffer(state, id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class App extends Component {
|
export default class App extends Component {
|
||||||
client = null;
|
|
||||||
state = {
|
state = {
|
||||||
connectParams: {
|
connectParams: {
|
||||||
serverURL: null,
|
serverURL: null,
|
||||||
@ -157,6 +156,7 @@ export default class App extends Component {
|
|||||||
activeBuffer: null,
|
activeBuffer: null,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
clients = new Map();
|
||||||
pendingHistory = Promise.resolve(null);
|
pendingHistory = Promise.resolve(null);
|
||||||
endOfHistory = new Map();
|
endOfHistory = new Map();
|
||||||
receipts = new Map();
|
receipts = new Map();
|
||||||
@ -368,10 +368,12 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMessage(netID, bufName, msg) {
|
addMessage(netID, bufName, msg) {
|
||||||
|
var client = this.clients.get(netID);
|
||||||
|
|
||||||
msg.key = messagesCount;
|
msg.key = messagesCount;
|
||||||
messagesCount++;
|
messagesCount++;
|
||||||
|
|
||||||
msg.isHighlight = irc.isHighlight(msg, this.client.nick);
|
msg.isHighlight = irc.isHighlight(msg, client.nick);
|
||||||
|
|
||||||
if (!msg.tags) {
|
if (!msg.tags) {
|
||||||
msg.tags = {};
|
msg.tags = {};
|
||||||
@ -393,7 +395,7 @@ export default class App extends Component {
|
|||||||
if (msg.isHighlight) {
|
if (msg.isHighlight) {
|
||||||
msgUnread = Unread.HIGHLIGHT;
|
msgUnread = Unread.HIGHLIGHT;
|
||||||
kind = "highlight";
|
kind = "highlight";
|
||||||
} else if (target == this.client.nick) {
|
} else if (target == client.nick) {
|
||||||
msgUnread = Unread.HIGHLIGHT;
|
msgUnread = Unread.HIGHLIGHT;
|
||||||
kind = "private message";
|
kind = "private message";
|
||||||
} else {
|
} else {
|
||||||
@ -416,7 +418,7 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.prefix.name != this.client.nick && (msg.command != "PART" && msg.comand != "QUIT")) {
|
if (msg.prefix.name != client.nick && (msg.command != "PART" && msg.comand != "QUIT")) {
|
||||||
this.createBuffer(netID, bufName);
|
this.createBuffer(netID, bufName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +458,7 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
this.setState({ connectParams: params });
|
this.setState({ connectParams: params });
|
||||||
|
|
||||||
this.client = new Client({
|
var client = new Client({
|
||||||
url: params.serverURL,
|
url: params.serverURL,
|
||||||
pass: params.serverPass,
|
pass: params.serverPass,
|
||||||
nick: params.nick,
|
nick: params.nick,
|
||||||
@ -465,15 +467,17 @@ export default class App extends Component {
|
|||||||
saslPlain: params.saslPlain,
|
saslPlain: params.saslPlain,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.addEventListener("close", () => {
|
this.clients.set(netID, client);
|
||||||
|
|
||||||
|
client.addEventListener("close", () => {
|
||||||
this.handleClose(netID);
|
this.handleClose(netID);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.addEventListener("message", (event) => {
|
client.addEventListener("message", (event) => {
|
||||||
this.handleMessage(netID, event.detail.message);
|
this.handleMessage(netID, event.detail.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.addEventListener("error", (event) => {
|
client.addEventListener("error", (event) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
error: event.detail,
|
error: event.detail,
|
||||||
});
|
});
|
||||||
@ -509,10 +513,11 @@ export default class App extends Component {
|
|||||||
clearTimeout(this.reconnectTimeoutID);
|
clearTimeout(this.reconnectTimeoutID);
|
||||||
this.reconnectTimeoutID = null;
|
this.reconnectTimeoutID = null;
|
||||||
|
|
||||||
if (this.client) {
|
var client = this.clients.get(netID);
|
||||||
|
if (client) {
|
||||||
// Prevent auto-reconnect from kicking in
|
// Prevent auto-reconnect from kicking in
|
||||||
this.client.removeEventListener("close", this.handleClose);
|
client.removeEventListener("close", this.handleClose);
|
||||||
this.client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setNetworkState(netID, { status: Status.DISCONNECTED });
|
this.setNetworkState(netID, { status: Status.DISCONNECTED });
|
||||||
@ -530,12 +535,13 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMessage(netID, msg) {
|
handleMessage(netID, msg) {
|
||||||
|
var client = this.clients.get(netID);
|
||||||
switch (msg.command) {
|
switch (msg.command) {
|
||||||
case irc.RPL_WELCOME:
|
case irc.RPL_WELCOME:
|
||||||
this.setNetworkState(netID, { status: Status.REGISTERED });
|
this.setNetworkState(netID, { status: Status.REGISTERED });
|
||||||
|
|
||||||
if (this.state.connectParams.autojoin.length > 0) {
|
if (this.state.connectParams.autojoin.length > 0) {
|
||||||
this.client.send({
|
client.send({
|
||||||
command: "JOIN",
|
command: "JOIN",
|
||||||
params: [this.state.connectParams.autojoin.join(",")],
|
params: [this.state.connectParams.autojoin.join(",")],
|
||||||
});
|
});
|
||||||
@ -617,7 +623,7 @@ export default class App extends Component {
|
|||||||
case "NOTICE":
|
case "NOTICE":
|
||||||
case "PRIVMSG":
|
case "PRIVMSG":
|
||||||
var target = msg.params[0];
|
var target = msg.params[0];
|
||||||
if (target == this.client.nick) {
|
if (target == client.nick) {
|
||||||
target = msg.prefix.name;
|
target = msg.prefix.name;
|
||||||
}
|
}
|
||||||
this.addMessage(netID, target, msg);
|
this.addMessage(netID, target, msg);
|
||||||
@ -631,7 +637,7 @@ export default class App extends Component {
|
|||||||
members.set(msg.prefix.name, null);
|
members.set(msg.prefix.name, null);
|
||||||
return { members };
|
return { members };
|
||||||
});
|
});
|
||||||
if (msg.prefix.name != this.client.nick) {
|
if (msg.prefix.name != client.nick) {
|
||||||
this.addMessage(netID, channel, msg);
|
this.addMessage(netID, channel, msg);
|
||||||
}
|
}
|
||||||
if (channel == this.state.connectParams.autojoin[0]) {
|
if (channel == this.state.connectParams.autojoin[0]) {
|
||||||
@ -640,10 +646,10 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var receipt = this.getReceipt(channel, ReceiptType.READ);
|
var receipt = this.getReceipt(channel, ReceiptType.READ);
|
||||||
if (msg.prefix.name == this.client.nick && receipt && this.client.enabledCaps["draft/chathistory"] && this.client.enabledCaps["server-time"]) {
|
if (msg.prefix.name == client.nick && receipt && client.enabledCaps["draft/chathistory"] && client.enabledCaps["server-time"]) {
|
||||||
var after = receipt;
|
var after = receipt;
|
||||||
var before = { time: msg.tags.time || irc.formatDate(new Date()) };
|
var before = { time: msg.tags.time || irc.formatDate(new Date()) };
|
||||||
this.fetchHistoryBetween(channel, after, before, CHATHISTORY_MAX_SIZE).catch((err) => {
|
this.fetchHistoryBetween(client, channel, after, before, CHATHISTORY_MAX_SIZE).catch((err) => {
|
||||||
this.setState({ error: "Failed to fetch history: " + err });
|
this.setState({ error: "Failed to fetch history: " + err });
|
||||||
this.receipts.delete(channel);
|
this.receipts.delete(channel);
|
||||||
this.saveReceipts();
|
this.saveReceipts();
|
||||||
@ -660,7 +666,7 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
this.addMessage(netID, channel, msg);
|
this.addMessage(netID, channel, msg);
|
||||||
|
|
||||||
if (msg.prefix.name == this.client.nick) {
|
if (msg.prefix.name == client.nick) {
|
||||||
this.receipts.delete(channel);
|
this.receipts.delete(channel);
|
||||||
this.saveReceipts();
|
this.saveReceipts();
|
||||||
}
|
}
|
||||||
@ -753,13 +759,16 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open(target) {
|
open(target) {
|
||||||
|
var netID = getActiveNetworkID(this.state);
|
||||||
|
var client = this.clients.get(netID);
|
||||||
|
|
||||||
if (this.isChannel(target)) {
|
if (this.isChannel(target)) {
|
||||||
this.client.send({ command: "JOIN", params: [target] });
|
client.send({ command: "JOIN", params: [target] });
|
||||||
} else {
|
} else {
|
||||||
this.client.send({ command: "WHO", params: [target] });
|
client.send({ command: "WHO", params: [target] });
|
||||||
}
|
}
|
||||||
this.createBuffer(getActiveNetworkID(this.state), target);
|
this.createBuffer(netID, target);
|
||||||
this.switchBuffer({ name: target });
|
this.switchBuffer({ network: netID, name: target });
|
||||||
}
|
}
|
||||||
|
|
||||||
close(id) {
|
close(id) {
|
||||||
@ -782,17 +791,18 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case BufferType.CHANNEL:
|
case BufferType.CHANNEL:
|
||||||
this.client.send({ command: "PART", params: [buf.name] });
|
var client = this.clients.get(buf.network);
|
||||||
|
client.send({ command: "PART", params: [buf.name] });
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case BufferType.NICK:
|
case BufferType.NICK:
|
||||||
this.switchBuffer({ name: SERVER_BUFFER });
|
this.switchBuffer({ name: SERVER_BUFFER });
|
||||||
this.setState((state) => {
|
this.setState((state) => {
|
||||||
var buffers = new Map(state.buffers);
|
var buffers = new Map(state.buffers);
|
||||||
buffers.delete(target);
|
buffers.delete(buf.name);
|
||||||
return { buffers };
|
return { buffers };
|
||||||
});
|
});
|
||||||
|
|
||||||
this.receipts.delete(target);
|
this.receipts.delete(buf.name);
|
||||||
this.saveReceipts();
|
this.saveReceipts();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -822,12 +832,15 @@ export default class App extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = { command: "PRIVMSG", params: [target, text] };
|
var netID = getActiveNetworkID(this.state);
|
||||||
this.client.send(msg);
|
var client = this.clients.get(netID);
|
||||||
|
|
||||||
if (!this.client.enabledCaps["echo-message"]) {
|
var msg = { command: "PRIVMSG", params: [target, text] };
|
||||||
msg.prefix = { name: this.client.nick };
|
client.send(msg);
|
||||||
this.addMessage(getActiveNetworkID(this.state), target, msg);
|
|
||||||
|
if (!client.enabledCaps["echo-message"]) {
|
||||||
|
msg.prefix = { name: client.nick };
|
||||||
|
this.addMessage(netID, target, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,7 +875,11 @@ export default class App extends Component {
|
|||||||
if (!channel) {
|
if (!channel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.client.send({ command: "JOIN", params: [channel] });
|
|
||||||
|
var netID = getActiveNetworkID(this.state);
|
||||||
|
var client = this.clients.get(netID);
|
||||||
|
|
||||||
|
client.send({ command: "JOIN", params: [channel] });
|
||||||
}
|
}
|
||||||
|
|
||||||
autocomplete(prefix) {
|
autocomplete(prefix) {
|
||||||
@ -895,7 +912,7 @@ export default class App extends Component {
|
|||||||
return fromList(buf.members.keys(), prefix);
|
return fromList(buf.members.keys(), prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
roundtripChatHistory(params) {
|
roundtripChatHistory(client, params) {
|
||||||
// Don't send multiple CHATHISTORY commands in parallel, we can't
|
// Don't send multiple CHATHISTORY commands in parallel, we can't
|
||||||
// properly handle batches and errors.
|
// properly handle batches and errors.
|
||||||
this.pendingHistory = this.pendingHistory.catch(() => {}).then(() => {
|
this.pendingHistory = this.pendingHistory.catch(() => {}).then(() => {
|
||||||
@ -903,7 +920,7 @@ export default class App extends Component {
|
|||||||
command: "CHATHISTORY",
|
command: "CHATHISTORY",
|
||||||
params,
|
params,
|
||||||
};
|
};
|
||||||
return this.client.roundtrip(msg, (event) => {
|
return client.roundtrip(msg, (event) => {
|
||||||
var msg = event.detail.message;
|
var msg = event.detail.message;
|
||||||
|
|
||||||
switch (msg.command) {
|
switch (msg.command) {
|
||||||
@ -913,7 +930,7 @@ export default class App extends Component {
|
|||||||
if (enter) {
|
if (enter) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var batch = this.client.batches.get(name);
|
var batch = client.batches.get(name);
|
||||||
if (batch.type == "chathistory") {
|
if (batch.type == "chathistory") {
|
||||||
return batch;
|
return batch;
|
||||||
}
|
}
|
||||||
@ -930,10 +947,10 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch history in ascending order */
|
/* Fetch history in ascending order */
|
||||||
fetchHistoryBetween(target, after, before, limit) {
|
fetchHistoryBetween(client, target, after, before, limit) {
|
||||||
var max = Math.min(limit, CHATHISTORY_PAGE_SIZE);
|
var max = Math.min(limit, CHATHISTORY_PAGE_SIZE);
|
||||||
var params = ["AFTER", target, "timestamp=" + after.time, max];
|
var params = ["AFTER", target, "timestamp=" + after.time, max];
|
||||||
return this.roundtripChatHistory(params).then((batch) => {
|
return this.roundtripChatHistory(client, params).then((batch) => {
|
||||||
limit -= batch.messages.length;
|
limit -= batch.messages.length;
|
||||||
if (limit <= 0) {
|
if (limit <= 0) {
|
||||||
throw new Error("Cannot fetch all chat history: too many messages");
|
throw new Error("Cannot fetch all chat history: too many messages");
|
||||||
@ -941,7 +958,7 @@ export default class App extends Component {
|
|||||||
if (batch.messages.length == max) {
|
if (batch.messages.length == max) {
|
||||||
// There are still more messages to fetch
|
// There are still more messages to fetch
|
||||||
after.time = batch.messages[batch.messages.length - 1].tags.time;
|
after.time = batch.messages[batch.messages.length - 1].tags.time;
|
||||||
return this.fetchHistoryBetween(target, after, before, limit);
|
return this.fetchHistoryBetween(client, target, after, before, limit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -951,7 +968,10 @@ export default class App extends Component {
|
|||||||
if (!buf || buf.type == BufferType.SERVER) {
|
if (!buf || buf.type == BufferType.SERVER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.client.enabledCaps["draft/chathistory"] || !this.client.enabledCaps["server-time"]) {
|
|
||||||
|
var client = this.clients.get(buf.network);
|
||||||
|
|
||||||
|
if (!client.enabledCaps["draft/chathistory"] || !client.enabledCaps["server-time"]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.endOfHistory.get(buf.id)) {
|
if (this.endOfHistory.get(buf.id)) {
|
||||||
@ -969,7 +989,7 @@ export default class App extends Component {
|
|||||||
this.endOfHistory.set(buf.id, true);
|
this.endOfHistory.set(buf.id, true);
|
||||||
|
|
||||||
var params = ["BEFORE", buf.name, "timestamp=" + before, CHATHISTORY_PAGE_SIZE];
|
var params = ["BEFORE", buf.name, "timestamp=" + before, CHATHISTORY_PAGE_SIZE];
|
||||||
this.roundtripChatHistory(params).then((batch) => {
|
this.roundtripChatHistory(client, params).then((batch) => {
|
||||||
this.endOfHistory.set(buf.id, batch.messages.length < CHATHISTORY_PAGE_SIZE);
|
this.endOfHistory.set(buf.id, batch.messages.length < CHATHISTORY_PAGE_SIZE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user