import { html, Component } from "../lib/index.js"; import { BufferType, getBufferURL, getServerName } from "../state.js"; import * as irc from "../lib/irc.js"; class SwitcherItem extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(event) { event.preventDefault(); this.props.onClick(); } render() { let class_ = this.props.selected ? "selected" : ""; return html`
  • ${getServerName(this.props.server, this.props.bouncerNetwork)} ${this.props.buffer.name}
  • `; } } function matchString(s, query) { return s.toLowerCase().includes(query) ? 1 : 0; } function matchBuffer(buf, server, query) { let score = 2 * matchString(buf.name, query); switch (buf.type) { case BufferType.CHANNEL: score += matchString(buf.topic || "", query); break; case BufferType.NICK: let user = server.users.get(buf.name); if (user && user.realname && irc.isMeaningfulRealname(user.realname, buf.name)) { score += matchString(user.realname, query); } break; } return score; } export default class SwitcherForm extends Component { state = { query: "", selected: 0, }; constructor(props) { super(props); this.handleInput = this.handleInput.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.handleKeyUp = this.handleKeyUp.bind(this); } getSuggestions() { let query = this.state.query.toLowerCase(); let l = []; let scores = new Map(); for (let buf of this.props.buffers.values()) { if (buf.type === BufferType.SERVER) { continue; } let score = 0; if (query !== "") { let server = this.props.servers.get(buf.server); score = matchBuffer(buf, server, query); if (!score) { continue; } } scores.set(buf.id, score); l.push(buf); } l.sort((a, b) => { return scores.get(b.id) - scores.get(a.id); }); return l.slice(0, 20); } handleInput(event) { let target = event.target; this.setState({ [target.name]: target.value }); } handleSubmit(event) { event.preventDefault(); this.props.onSubmit(this.getSuggestions()[this.state.selected]); } handleKeyUp(event) { switch (event.key) { case "ArrowUp": event.stopPropagation(); this.move(-1); break; case "ArrowDown": event.stopPropagation(); this.move(1); break; } } move(delta) { let numSuggestions = this.getSuggestions().length; this.setState((state) => { return { selected: (state.selected + delta + numSuggestions) % numSuggestions, }; }); } render() { let items = this.getSuggestions().map((buf, i) => { let server = this.props.servers.get(buf.server); let bouncerNetwork = null; if (server.bouncerNetID) { bouncerNetwork = this.props.bouncerNetworks.get(server.bouncerNetID); } return html` <${SwitcherItem} buffer=${buf} server=${server} bouncerNetwork=${bouncerNetwork} selected=${this.state.selected === i} onClick=${() => this.props.onSubmit(buf)} /> `; }); return html`
    `; } }