Fix autocompletion

This commit is contained in:
Pavel Djundik 2018-07-08 17:57:02 +03:00 committed by Pavel Djundik
parent 0e930c9356
commit 09fa3e5c86
7 changed files with 66 additions and 72 deletions

View file

@ -174,7 +174,7 @@ export default {
},
destroyed() {
if (this.historyObserver) {
this.historyObserver.unobserve(this.$refs.loadMoreButton);
this.historyObserver.disconnect();
}
},
methods: {

View file

@ -30,6 +30,14 @@ export default {
network: Object,
channel: Object,
},
mounted() {
if (this.$root.settings.autocomplete) {
require("../js/autocompletion").enable();
}
},
destroyed() {
require("../js/autocompletion").disable();
},
methods: {
getInputPlaceholder(channel) {
if (channel.type === "channel" || channel.type === "query") {

View file

@ -5,9 +5,10 @@ const fuzzy = require("fuzzy");
const Mousetrap = require("mousetrap");
const {Textcomplete, Textarea} = require("textcomplete");
const emojiMap = require("./libs/simplemap.json");
const options = require("./options");
const constants = require("./constants");
const {vueApp} = require("./vue");
let input;
let textcomplete;
let enabled = false;
@ -15,7 +16,6 @@ module.exports = {
enable: enableAutocomplete,
disable() {
if (enabled) {
const input = $("#input");
input.off("input.tabcomplete");
Mousetrap(input.get(0)).unbind("tab", "keydown");
textcomplete.destroy();
@ -69,7 +69,7 @@ const nicksStrategy = {
},
replace([, original], position = 1) {
// If no postfix specified, return autocompleted nick as-is
if (!options.settings.nickPostfix) {
if (!vueApp.settings.nickPostfix) {
return original;
}
@ -79,7 +79,7 @@ const nicksStrategy = {
}
// If nick is first in the input, append specified postfix
return original + options.settings.nickPostfix;
return original + vueApp.settings.nickPostfix;
},
index: 1,
};
@ -179,7 +179,7 @@ function enableAutocomplete() {
let tabCount = 0;
let lastMatch = "";
let currentMatches = [];
const input = $("#input");
input = $("#input");
input.on("input.tabcomplete", () => {
tabCount = 0;
@ -270,19 +270,17 @@ function fuzzyGrep(term, array) {
}
function rawNicks() {
const chan = chat.find(".active");
const users = chan.find(".userlist");
if (vueApp.activeChannel.channel.users.length > 0) {
const users = vueApp.activeChannel.channel.users.slice();
// If this channel has a list of nicks, just return it
if (users.length > 0) {
return users.data("nicks");
return users.sort((a, b) => b.lastMessage - a.lastMessage).map((u) => u.nick);
}
const me = $("#nick").text();
const otherUser = chan.attr("aria-label");
const me = vueApp.activeChannel.network.nick;
const otherUser = vueApp.activeChannel.channel.name;
// If this is a query, add their name to autocomplete
if (me !== otherUser && chan.data("type") === "query") {
if (me !== otherUser && vueApp.activeChannel.channel.type === "query") {
return [otherUser, me];
}
@ -313,16 +311,11 @@ function completeCommands(word) {
function completeChans(word) {
const words = [];
sidebar.find(".chan.active")
.parent()
.find(".chan")
.each(function() {
const self = $(this);
if (self.hasClass("channel")) {
words.push(self.attr("aria-label"));
}
});
for (const channel of vueApp.activeChannel.network.channels) {
if (channel.type === "channel") {
words.push(channel.name);
}
}
return fuzzyGrep(word, words);
}

View file

@ -5,21 +5,22 @@ const $ = require("jquery");
const moment = require("moment");
// our libraries
require("./libs/jquery/stickyscroll");
const slideoutMenu = require("./slideout");
const templates = require("../views");
const socket = require("./socket");
require("./socket-events");
const storage = require("./localStorage");
const utils = require("./utils");
require("./webpush");
require("./keybinds");
require("./clipboard");
const contextMenuFactory = require("./contextMenuFactory");
const {vueApp, findChannel} = require("./vue");
$(function() {
window.vueMounted = () => {
require("./socket-events");
require("./libs/jquery/stickyscroll");
const slideoutMenu = require("./slideout");
const templates = require("../views");
const contextMenuFactory = require("./contextMenuFactory");
const storage = require("./localStorage");
const utils = require("./utils");
require("./webpush");
require("./keybinds");
require("./clipboard");
const sidebar = $("#sidebar, #footer");
const chat = $("#chat");
@ -353,4 +354,4 @@ $(function() {
// Only start opening socket.io connection after all events have been registered
socket.open();
});
};

View file

@ -5,6 +5,8 @@ const escapeRegExp = require("lodash/escapeRegExp");
const storage = require("./localStorage");
const tz = require("./libs/handlebars/tz");
const socket = require("./socket");
const {vueApp} = require("./vue");
require("../js/autocompletion");
const $windows = $("#windows");
const $chat = $("#chat");
@ -23,24 +25,7 @@ let $warningUnsupported;
let $warningBlocked;
// Default settings
const settings = {
syncSettings: false,
advanced: false,
autocomplete: true,
nickPostfix: "",
coloredNicks: true,
desktopNotifications: false,
highlights: [],
links: true,
motd: true,
notification: true,
notifyAllMessages: false,
showSeconds: false,
statusMessages: "condensed",
theme: $("#theme").attr("data-server-theme"),
media: true,
userStyles: "",
};
const settings = vueApp.settings;
const noSync = ["syncSettings"];
@ -87,9 +72,6 @@ module.exports = {
initialize,
};
// Due to cyclical dependency, have to require it after exports
const autocompletion = require("./autocompletion");
function shouldOpenMessagePreview(type) {
return type === "link" ? settings.links : settings.media;
}
@ -155,12 +137,6 @@ function applySetting(name, value) {
$(this).text(tz($(this).parent().data("time")));
});
$chat.toggleClass("show-seconds", value);
} else if (name === "autocomplete") {
if (value) {
autocompletion.enable();
} else {
autocompletion.disable();
}
} else if (name === "desktopNotifications") {
if (("Notification" in window) && value && Notification.permission !== "granted") {
Notification.requestPermission(updateDesktopNotificationStatus);

View file

@ -107,16 +107,11 @@ function processReceivedMessage(data) {
render.trimMessageInChannel(channelContainer, messageLimit);
}
if ((data.msg.type === "message" || data.msg.type === "action") && channelContainer.hasClass("channel")) {
const nicks = channelContainer.find(".userlist").data("nicks");
if ((data.msg.type === "message" || data.msg.type === "action") && channel.channel.type === "channel") {
const user = channel.channel.users.find((u) => u.nick === data.msg.from.nick);
if (nicks) {
const find = nicks.indexOf(data.msg.from.nick);
if (find !== -1) {
nicks.splice(find, 1);
nicks.unshift(data.msg.from.nick);
}
if (user) {
user.lastMessage = (new Date(data.msg.time)).getTime() || Date.now();
}
}
}

View file

@ -24,12 +24,33 @@ const vueApp = new Vue({
appName: document.title,
activeChannel: null,
networks: [],
settings: {
syncSettings: false,
advanced: false,
autocomplete: true,
nickPostfix: "",
coloredNicks: true,
desktopNotifications: false,
highlights: [],
links: true,
motd: true,
notification: true,
notifyAllMessages: false,
showSeconds: false,
statusMessages: "condensed",
theme: document.getElementById("theme").dataset.serverTheme,
media: true,
userStyles: "",
},
},
render(createElement) {
return createElement(App, {
props: this,
});
},
mounted() {
Vue.nextTick(() => window.vueMounted());
}
});
function findChannel(id) {