abstract client functionality into its own module

This commit is contained in:
Iuri Matias 2018-12-22 10:24:39 -05:00
parent d968103bbd
commit 7e54d33a73
13 changed files with 492 additions and 79 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules
dist dist
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
TODO

65
package-lock.json generated
View File

@ -67,14 +67,6 @@
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}, },
"async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
"requires": {
"lodash": "^4.17.10"
}
},
"async-limiter": { "async-limiter": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
@ -1222,10 +1214,10 @@
"sha3": "^1.1.0" "sha3": "^1.1.0"
} }
}, },
"lodash": { "lodash.isequal": {
"version": "4.17.11", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
}, },
"lowercase-keys": { "lowercase-keys": {
"version": "1.0.1", "version": "1.0.1",
@ -1698,6 +1690,14 @@
"inherits": "^2.0.1" "inherits": "^2.0.1"
} }
}, },
"rxjs": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
"integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
"requires": {
"tslib": "^1.9.0"
}
},
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -2012,6 +2012,11 @@
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
"integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
}, },
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
"tunnel-agent": { "tunnel-agent": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@ -2034,14 +2039,6 @@
"mime-types": "~2.1.18" "mime-types": "~2.1.18"
} }
}, },
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"requires": {
"is-typedarray": "^1.0.0"
}
},
"ultron": { "ultron": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
@ -2389,8 +2386,17 @@
"integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==", "integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==",
"requires": { "requires": {
"underscore": "1.8.3", "underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.36", "web3-core-helpers": "1.0.0-beta.36"
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" },
"dependencies": {
"websocket": {
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
"from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
"requires": {
"debug": "^2.2.0",
"nan": "^2.3.3"
}
}
} }
}, },
"web3-shh": { "web3-shh": {
@ -2425,16 +2431,6 @@
} }
} }
}, },
"websocket": {
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
"from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
"requires": {
"debug": "^2.2.0",
"nan": "^2.3.3",
"typedarray-to-buffer": "^3.1.2",
"yaeti": "^0.0.6"
}
},
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@ -2501,11 +2497,6 @@
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}, },
"yaeti": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
},
"yauzl": { "yauzl": {
"version": "2.10.0", "version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",

View File

@ -37,7 +37,9 @@
"homepage": "https://github.com/status-im/status-x#readme", "homepage": "https://github.com/status-im/status-x#readme",
"dependencies": { "dependencies": {
"colors": "^1.3.2", "colors": "^1.3.2",
"lodash.isequal": "^4.5.0",
"neo-blessed": "^0.2.0", "neo-blessed": "^0.2.0",
"rxjs": "^6.3.3",
"status-js-api": "^1.0.5" "status-js-api": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,75 +1,76 @@
const Events = require("events"); const Events = require("events");
import Users from "./users";
import colors from "colors"; import colors from "colors";
class ChannelManager { class ChannelManager {
public channels: any[]; public channels: any[];
public events: any; public events: any;
public allUsers: Users;
private currentChannel: number; private currentChannel: number;
constructor() { constructor() {
this.channels = []; this.channels = [];
this.events = new Events(); this.events = new Events();
this.currentChannel = 0; this.currentChannel = 0;
this.allUsers = new Users();
} }
public addChannel(channelName: string, type: string, extraData?: any) { public addChannel(channelName: string, channelObject: any) {
if (this.getChannel(channelName)) { const channel = {name: channelName, pendingMessages: [], channel: channelObject, users: [], typingUsers: []};
return;
}
const channel = {name: channelName, pendingMessages: [], type, ...extraData};
channel.users = new Users();
this.channels.push(channel); this.channels.push(channel);
this.events.emit("update"); this.currentChannel = this.channels.length;
this.events.emit("channelSwitch");
this.events.emit("updateChannels", this.getChannelList());
} }
public getChannel(channelName: string) { public getChannel(channelName: string) {
return this.channels.find((c) => c.name === channelName); return this.channels.find((c) => c.name === channelName);
} }
public updateChannelUsers(channelName: string, users: any) {
this.getChannel(channelName).users = users;
this.events.emit("updateUsers", channelName, users);
}
public updateChannelTypingUsers(channelName: string, typingUsers: any) {
this.getChannel(channelName).typingUsers = typingUsers;
this.events.emit("updateTypingUsers", channelName, typingUsers);
}
public getCurrentChannel() { public getCurrentChannel() {
return this.channels[this.currentChannel]; return this.channels[this.currentChannel - 1];
} }
public addMessage(channelName: string, message: string, pubkey: string, username: string) { public addMessage(channelName: string, message: string, pubkey: string, username: string) {
const channel = this.getChannel(channelName); const channel = this.getChannel(channelName);
if (channelName !== this.channels[this.currentChannel].name) { if (channelName !== this.getCurrentChannel().name) {
channel.pendingMessages.push({pubkey, username, message}); channel.pendingMessages.push({pubkey, username, message});
} else { } else {
this.events.emit("newMessage", channelName, username, message); this.events.emit("newMessage", channelName, username, message);
} }
const user = this.allUsers.addOrUpdateUserKey(pubkey, username);
channel.users.addUserOrUpdate(user);
this.events.emit("update"); this.events.emit("update");
} }
public dumpPendingMessages() { public dumpPendingMessages() {
const messages = this.channels[this.currentChannel].pendingMessages.slice(0); const messages = this.getCurrentChannel().pendingMessages.slice(0);
this.channels[this.currentChannel].pendingMessages = []; this.getCurrentChannel().pendingMessages = [];
return messages; return messages;
} }
public switchChannelIndex(index: number) { public switchChannelIndex(index: number) {
if (index < 0) { if (index <= 0) {
return; return;
} }
if (index >= this.channels.length) { if (index > this.channels.length) {
return; return;
} }
this.currentChannel = index; this.currentChannel = index;
this.events.emit("update");
this.events.emit("channelSwitch"); this.events.emit("channelSwitch");
this.events.emit("updateChannels", this.getChannelList());
} }
public getChannelList() { public getChannelList() {
return this.channels.map((c) => { return this.channels.map((c) => {
const prefix = c.type === "channel" ? "#" : ""; const prefix = c.type === "channel" ? "#" : "";
if (c.name === this.channels[this.currentChannel].name) { if (c.name === this.getCurrentChannel().name) {
return colors.green(`${prefix}${c.name}`); return colors.green(`${prefix}${c.name}`);
} }
if (c.pendingMessages.length === 0) { if (c.pendingMessages.length === 0) {
@ -78,15 +79,7 @@ class ChannelManager {
return `${prefix}${c.name} (${c.pendingMessages.length})`; return `${prefix}${c.name} (${c.pendingMessages.length})`;
}); });
} }
public getUsersInCurrentChannel() {
const channel = this.getCurrentChannel();
const userKeys = channel.users.getUsers();
const users = userKeys.map((pubkey: string) => {
return this.allUsers.users[pubkey];
});
return users;
}
} }
export default ChannelManager; export default ChannelManager;

View File

@ -1,6 +1,8 @@
import StatusJS from "status-js-api"; import StatusJS from "status-js-api";
import UI from "./ui"; import UI from "./ui";
import ChannelManager from "./channelManager"; import ChannelManager from "./status-js-client/channelManager";
import StatusJSClient from "./status-js-client";
const DEFAULT_CHANNEL = "mytest"; const DEFAULT_CHANNEL = "mytest";
const CONTACT_CODE_REGEXP = /^(0x)?[0-9a-f]{130}$/i; const CONTACT_CODE_REGEXP = /^(0x)?[0-9a-f]{130}$/i;

127
src/index2.ts Normal file
View File

@ -0,0 +1,127 @@
import StatusJSClient from "./status-js-client/index";
import UI from "./ui";
import ChannelManager from "./channelManager";
const ui = new UI();
ui.logEntry(`
Welcome to
_________ __ __ ____ ___
/ _____// |______ _/ |_ __ __ _____\\ \\/ /
\\_____ \\\\ __\\__ \\\\ __\\ | \\/ ___/\\ /
/ \\| | / __ \\| | | | /\\___ \\ / \\
/_______ /|__| (____ /__| |____//____ >___/\\ \\
\\/ \\/ \\/ \\_/
`);
ui.logEntry(`Generating Identity....`);
ui.logEntry(`Connecting to Peers....`);
ui.logEntry(`Rejoining Channels....`);
(async () => {
const status = new StatusJSClient();
await status.connectToNode("ws://localhost:8546")
const userPubKey = await status.getPublicKey();
ui.logEntry(`PK: ${userPubKey}`);
ui.logEntry(`-----------------------------------------------------------`);
const channelManager = new ChannelManager();
ui.events.on("cmd", async (cmd: string) => {
if (cmd.split(" ")[0] === "/join") {
const channelName = cmd.split(" ")[1].replace("#", "");
ui.logEntry("joining " + channelName);
if (channelManager.getChannel(channelName)) {
return ui.logEntry("you already joined this channel. you can switch channel with the /s <number> command");
}
let channel = await status.joinChannel(channelName);
channelManager.addChannel(channelName, channel);
channel.messagesObserver.subscribe((msg) => {
channelManager.addMessage(channelName, msg.message, msg.pubkey, msg.username);
});
channel.usersObserver.subscribe((users) => {
channelManager.updateChannelUsers(channelName, users);
})
channel.usersTypingObserver.subscribe((typingUsers) => {
channelManager.updateChannelTypingUsers(channelName, typingUsers);
});
return;
}
if (cmd.split(" ")[0] === "/s") {
const channelNumber = cmd.split(" ")[1];
channelManager.switchChannelIndex(parseInt(channelNumber, 10));
return;
}
const currentChannel = channelManager.getCurrentChannel();
if (!currentChannel) {
ui.logEntry("not in any channel; try /join #mytest");
return;
}
channelManager.getCurrentChannel().channel.sendMessage(cmd);
});
ui.events.on("typing", (currentText: string) => {
if (currentText[0] === "/") {
return;
}
const currentChannel = channelManager.getCurrentChannel();
if (!currentChannel) return;
currentChannel.channel.typingEvent();
});
channelManager.events.on("newMessage", (channelName: string, username: string, message: string) => {
const msg = (username + ">").green + " " + message;
ui.logEntry(msg);
});
channelManager.events.on("channelSwitch", () => {
const currentChannel = channelManager.getCurrentChannel();
ui.logEntry("-------------------");
ui.logEntry("now viewing #" + currentChannel.name);
channelManager.dumpPendingMessages().forEach((message: any) => {
const msg = (message.username + ">").green + " " + message.message;
ui.logEntry(msg);
});
});
channelManager.events.on("updateUsers", (channelName, users) => {
if (channelName !== channelManager.getCurrentChannel().name) {
return;
}
ui.availableUsers(users.map((x: any) => {
return {name: x.username, status: (x.online ? "on" : "offline")};
}));
});
channelManager.events.on("updateTypingUsers", (channelName, typingUsers) => {
if (channelName !== channelManager.getCurrentChannel().name) {
return;
}
if (typingUsers.length === 0) {
return ui.setStatus("");
}
if (typingUsers.length === 1) {
return ui.setStatus(typingUsers[0] + " is typing");
}
return ui.setStatus(typingUsers.join(", ") + " are typing");
});
channelManager.events.on("updateChannels", ui.availableChannels.bind(this));
})();

View File

@ -0,0 +1,151 @@
import { Observable, fromEvent, interval } from 'rxjs';
import { throttle, map, distinctUntilChanged } from 'rxjs/operators';
import Events from 'events';
import isEqual from 'lodash.isequal';
class Channel {
private channelName: string;
private status: any;
public messagesObserver: any;
public usersTypingObserver: any;
public usersObserver: any;
private typingObserver: any;
constructor(channelName: string, status: any) {
this.status = status;
this.channelName = channelName;
this.events = new Events();
this.usersTyping = {};
this.users = {};
this.typingObserver = fromEvent(this.events, 'typing');
this.usersTypingObserver = fromEvent(this.events, 'usersTyping').pipe(
throttle(val => interval(450)),
map(() => Object.values(this.usersTyping).map(x => x.username)),
distinctUntilChanged(isEqual),
);
this.usersObserver = fromEvent(this.events, 'users').pipe(
throttle(val => interval(1000)),
map(() => Object.values(this.users).map((x) => {
return {username: x.username, online: x.online}
})),
distinctUntilChanged(isEqual),
);
}
public joinChannel(cb) {
this.status.joinChat(this.channelName, () => {
this.pingChannel();
this.listenToMessages();
this.listenToTyping();
this.listenToUsers();
cb();
});
}
private pingChannel() {
this.status.sendJsonMessage(this.channelName, {type: "ping"});
setInterval(() => {
this.status.sendJsonMessage(this.channelName, {type: "ping"});
}, 5 * 1000);
}
private listenToMessages() {
this.messagesObserver = Observable.create((observer) => {
this.status.onMessage(this.channelName, (err: any, data: any) => {
if (err || !data) {
console.dir("---- error ")
console.dir(err)
console.dir(data)
return observer.error(err);
}
const msg = JSON.parse(data.payload)[1][0];
if (JSON.parse(data.payload)[1][1] === "content/json") {
return;
}
this.usersTyping[data.data.sig] = {username: data.username, lastTyped: 0}; // user is likley no longer typing if a message was received
observer.next({message: msg, pubkey: data.data.sig, username: data.username});
this.events.emit('users')
});
});
this.status.onMessage(this.channelName, (err: any, data: any) => {
if (JSON.parse(data.payload)[1][1] !== "content/json") {
// usersTyping[data.data.sig] = 0; // user is likley no longer typing if a message was received
return;
}
const msg = JSON.parse(JSON.parse(data.payload)[1][0]);
const fromUser = data.data.sig;
if (msg.type === "ping") {
this.users[fromUser] = {
username: data.username,
lastSeen: (new Date().getTime()),
online: true
}
this.events.emit('users')
// const user = channels.allUsers.addOrUpdateUserKey(fromUser, data.username);
// const channel = channels.getChannel(channelName);
// channel.users.addUserOrUpdate(user);
// channels.events.emit("update");
}
if (msg.type === "typing") {
//if (fromUser === userPubKey) {
// return; // ignore typing events from self
//}
this.usersTyping[fromUser] = {username: data.username, lastTyped: (new Date().getTime()), online: true};
this.events.emit('usersTyping')
this.events.emit('users')
}
});
}
private listenToUsers() {
this.events.emit('users')
setInterval(() => {
const currentTime = (new Date().getTime());
for (const pubkey of Object.keys(this.users)) {
const user = this.users[pubkey];
if (currentTime - user.lastSeen > 10 * 1000) {
user.online = false;
}
}
this.events.emit('users')
}, 5000);
}
public listenToTyping() {
this.typingObserver.pipe(throttle(val => interval(3000))).subscribe(() => {
this.status.sendJsonMessage(this.channelName, {type: "typing"});
})
setInterval(() => {
const currentTime = (new Date().getTime());
for (const pubkey of Object.keys(this.usersTyping)) {
const lastTyped = this.usersTyping[pubkey].lastTyped;
if (currentTime - lastTyped > 3 * 1000 || currentTime < lastTyped) {
delete this.usersTyping[pubkey];
}
}
this.events.emit('usersTyping')
}, 500);
}
public typingEvent() {
this.events.emit('typing')
}
public sendMessage(msg: string) {
this.status.sendMessage(this.channelName, msg);
}
}
export default Channel;

View File

@ -0,0 +1,92 @@
const Events = require("events");
import Users from "./users";
import colors from "colors";
class ChannelManager {
public channels: any[];
public events: any;
public allUsers: Users;
private currentChannel: number;
constructor() {
this.channels = [];
this.events = new Events();
this.currentChannel = 0;
this.allUsers = new Users();
}
public addChannel(channelName: string, type: string, extraData?: any) {
if (this.getChannel(channelName)) {
return;
}
const channel = {name: channelName, pendingMessages: [], type, ...extraData};
channel.users = new Users();
this.channels.push(channel);
this.events.emit("update");
}
public getChannel(channelName: string) {
return this.channels.find((c) => c.name === channelName);
}
public getCurrentChannel() {
return this.channels[this.currentChannel];
}
public addMessage(channelName: string, message: string, pubkey: string, username: string) {
const channel = this.getChannel(channelName);
if (channelName !== this.channels[this.currentChannel].name) {
channel.pendingMessages.push({pubkey, username, message});
} else {
this.events.emit("newMessage", channelName, username, message);
}
const user = this.allUsers.addOrUpdateUserKey(pubkey, username);
channel.users.addUserOrUpdate(user);
this.events.emit("update");
}
public dumpPendingMessages() {
const messages = this.channels[this.currentChannel].pendingMessages.slice(0);
this.channels[this.currentChannel].pendingMessages = [];
return messages;
}
public switchChannelIndex(index: number) {
if (index < 0) {
return;
}
if (index >= this.channels.length) {
return;
}
this.currentChannel = index;
this.events.emit("update");
this.events.emit("channelSwitch");
}
public getChannelList() {
return this.channels.map((c) => {
const prefix = c.type === "channel" ? "#" : "";
if (c.name === this.channels[this.currentChannel].name) {
return colors.green(`${prefix}${c.name}`);
}
if (c.pendingMessages.length === 0) {
return `${prefix}${c.name}`;
}
return `${prefix}${c.name} (${c.pendingMessages.length})`;
});
}
public getUsersInCurrentChannel() {
const channel = this.getCurrentChannel();
const userKeys = channel.users.getUsers();
const users = userKeys.map((pubkey: string) => {
return this.allUsers.users[pubkey];
});
return users;
}
}
export default ChannelManager;

View File

@ -0,0 +1,57 @@
import StatusJS from "status-js-api";
import Channel from './channel';
interface ConfigOptions {
pingFrequency: number;
};
interface WhisperProvider {
send: Function;
sendAasync: Function;
}
class StatusJSClient {
private status: any;
private userPubKey: string;
private userName: string;
private channels: any;
constructor(options?: ConfigOptions) {
this.status = new StatusJS();
this.userPubKey = "";
this.userName = "";
this.channels = {};
}
public async connectToNode(url: string) {
await this.status.connect(url);
this.init();
}
public connectToProvider(provider: WhisperProvider) {
this.init();
}
private async init() {
this.userPubKey = await this.status.getPublicKey();
this.userName = await this.status.getUserName();
}
public async getPublicKey() {
const userPubKey = await this.status.getPublicKey();
return userPubKey;
}
public joinChannel(channelName: string) {
const channel = new Channel(channelName, this.status);
this.channels[channelName] = channel;
return new Promise((resolve: any, reject?: any) => {
channel.joinChannel(() => {
resolve(channel);
});
})
}
}
export default StatusJSClient;

View File

@ -70,13 +70,12 @@ class UI {
} }
public availableChannels(channels: string[]) { public availableChannels(channels: string[]) {
this.channels.setContent(channels.map((c, i) => `(${i}) ${c}`).join("\n")); this.channels.setContent(channels.map((c, i) => `(${i+1}) ${c}`).join("\n"));
this.screen.render(); this.screen.render();
} }
// TODO: to remove, might not be used anymore
private setStatus(status: string) { private setStatus(status: string) {
this.operations.setContent(status); this.consoleState.setContent(status);
this.screen.render(); this.screen.render();
} }

View File

@ -858,12 +858,6 @@ async-limiter@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
async@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
dependencies:
lodash "^4.17.10"
asynckit@^0.4.0: asynckit@^0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@ -2794,6 +2788,10 @@ lodash.debounce@^4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.5: lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.5:
version "4.17.11" version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
@ -3686,7 +3684,7 @@ run-async@^2.2.0:
dependencies: dependencies:
is-promise "^2.1.0" is-promise "^2.1.0"
rxjs@^6.1.0: rxjs@^6.1.0, rxjs@^6.3.3:
version "6.3.3" version "6.3.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55"
dependencies: dependencies: