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() { destroyed() {
if (this.historyObserver) { if (this.historyObserver) {
this.historyObserver.unobserve(this.$refs.loadMoreButton); this.historyObserver.disconnect();
} }
}, },
methods: { methods: {

View file

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

View file

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

View file

@ -5,21 +5,22 @@ const $ = require("jquery");
const moment = require("moment"); const moment = require("moment");
// our libraries // our libraries
require("./libs/jquery/stickyscroll");
const slideoutMenu = require("./slideout");
const templates = require("../views");
const socket = require("./socket"); 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"); 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 sidebar = $("#sidebar, #footer");
const chat = $("#chat"); const chat = $("#chat");
@ -353,4 +354,4 @@ $(function() {
// Only start opening socket.io connection after all events have been registered // Only start opening socket.io connection after all events have been registered
socket.open(); socket.open();
}); };

View file

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

View file

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

View file

@ -24,12 +24,33 @@ const vueApp = new Vue({
appName: document.title, appName: document.title,
activeChannel: null, activeChannel: null,
networks: [], 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) { render(createElement) {
return createElement(App, { return createElement(App, {
props: this, props: this,
}); });
}, },
mounted() {
Vue.nextTick(() => window.vueMounted());
}
}); });
function findChannel(id) { function findChannel(id) {