NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Emoji: Оптимизация + поиск по наборам // @namespace http://vk.com/ // @description Прокачивает понель смайлов ВКонтакте: При открытии стикеров по умолчанию выбирает смайлы (их открывает быстрее), появился поиск, при вводе в поиск переключает наборы, по табу выходит из поиска, при выходе из поиска переключает обратно в смайлы и сбрасывает поиск, отприсовывает только найденные наборы, вместо всех // @version 0.4 // @author Flyink13 // @match https://vk.com/* // @icon https://www.google.com/s2/favicons?domain=vk.com // @grant none // @copyright 2021, flyink13 (https://openuserjs.org/users/flyink13) // @license MIT // @updateURL https://openuserjs.org/meta/flyink13/Emoji_Оптимизация_+_поиск_по_наборам.meta.js // @downloadURL https://openuserjs.org/install/flyink13/Emoji_Оптимизация_+_поиск_по_наборам.user.js // ==/UserScript== /* global Emoji, ls, data, domPN, parseLatKeys */ function Main(ttl = 2) { // Отключаем у фреймов if (window != parent) { return; } // Проверяем, что модуль инициализирован if (typeof Emoji !== 'object') { // Мне лень писать нормальное условие, и так сойдет setTimeout(Main, ttl, Math.min(60000, ttl * 2)); return; } const KEYS = { LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, TAB: 9, }; // Запоминаем функции, которые будем заменять Emoji.getTabsCode_orginal = Emoji.getTabsCode; Emoji.ttClick_orginal = Emoji.ttClick; Emoji.hide_orginal = Emoji.hide; Emoji.getTabCont_original = Emoji.getTabCont; Emoji.tabSwitch_original = Emoji.tabSwitch; // Заменяем функцию получения вкладок набора стикеров Emoji.getTabsCode = (emoji, optId) => { // Функцию вызывают 2 раза, первый раз разрешаем, там смыйлы и еще что-то if (emoji !== window.emojiStickers) { return Emoji.getTabsCode_orginal(emoji, optId); } // По умолчанию рисуем избранное const systemPacks = window.emojiStickers.filter(([id]) => id < 0); const systemHtml = Emoji.getTabsCode_orginal(systemPacks, optId); // Поле ввода + контейнер с результатами return ` <input class="searchPackInput" style="" placeholder="Поиск" data-opt-id="${optId}" onkeydown="Emoji.onSearchPacksInputKeyDown(event);" oninput="Emoji.onSearchPacksInputChange(event);" /> <div class="searchPackContainer">${systemHtml}</div> `; } // Заменяем функцию открытия панели Emoji.ttClick = (optId, obj, needHide, needShow, ev, tabKey) => { ls && ls.set('stickers_tab', Emoji.TAB_EMOJI); const response = Emoji.ttClick_orginal(optId, obj, needHide, needShow, ev, tabKey); if (!obj || !obj.parentElement) { return; } if (needShow) { const input = obj.parentElement.parentElement.querySelector('.searchPackInput'); setTimeout(() => input && input.focus(), Emoji.SHOW_TT_TIMEOUT); } if (needHide) { Emoji.dropSearch(optId); } return response; } // Заменяем функцию скрытия панели Emoji.hide = (obj, ev, force) => { let optId = data(domPN(obj), 'optId'); Emoji.dropSearch(optId); return Emoji.hide_orginal(obj, ev, force); } Emoji.dropSearch = (optId) => { if (!Emoji.opts[optId] || !Emoji.opts[optId].tt) { return; } const tt = Emoji.opts[optId].tt; const txt = Emoji.opts[optId].txt; const selId = Emoji.TAB_EMOJI; const tabEl = tt.querySelector(`.emoji_tab_${selId}`); const input = tt.querySelector(`.searchPackInput`); // Возвращаем фокус на поле ввода Emoji.editableFocus(txt, false, true, void(0), true); setTimeout(() => { // Сбрасываем поле ввода input.value = ''; Emoji.onSearchPacksInputChange({ target: input }); // Переключаем вкладку на смайлы Emoji.tabSwitch(tabEl, selId, optId); }, Emoji.HIDE_TT_TIMEOUT); } Emoji.getTabCont = (optId, selId) => { const backup = window.emojiStickers; const activePacks = {}; activePacks[selId] = true; Emoji.opts[optId].searchResponse.forEach(([id]) => { activePacks[id] = true; }); window.emojiStickers = backup.filter(([id]) => activePacks[id]).splice(0, 8); const res = Emoji.getTabCont_original(optId, selId); window.emojiStickers = backup; return res; } Emoji.tabSwitch = (obj, selId, optId, ...args) => { const res = Emoji.tabSwitch_original(obj, selId, optId, ...args); Emoji.opts[optId].stickersInited = false; return res; } Emoji.onSearchPacksInputKeyDown = (event) => { const input = event.target; const optId = parseInt(input.dataset.optId, 10); if ([KEYS.UP, KEYS.DOWN, KEYS.LEFT, KEYS.RIGHT].indexOf(event.keyCode) === -1) { event.stopPropagation(); } if (event.keyCode !== KEYS.TAB || !Emoji.opts[optId]) { return; } Emoji.ttClick(optId, input, true); } Emoji.onSearchPacksInputChange = (event) => { const input = event.target; const optId = parseInt(input.dataset.optId, 10); const container = input.parentElement.querySelector('.searchPackContainer'); const searchResponse = window.emojiStickers.filter(([id]) => ( ( // При пустом поиске показываем избранное и последние наборы стикеров !input.value && id < 0 ) || ( // Ищем от двух символов input.value.length && Emoji.stickers[id] && Emoji.stickers[id].title && Emoji.stickers[id].title.toLowerCase().includes(input.value.toLowerCase()) ) )).splice(0, 8); container.innerHTML = Emoji.getTabsCode_orginal(searchResponse, optId); Emoji.opts[optId].searchResponse = searchResponse; if (input.value && searchResponse.length) { const selId = searchResponse[0][0]; const obj = container.querySelector(`.emoji_tab_${selId}`); Emoji.tabSwitch(obj, selId, optId); } } // Немного костыльных стилей 3-) const style = ` .searchPackInput { transition: all linear .2s; padding: 8px 12px; border: 0px; margin: 1px; width: 120px; float: left; background: #fff; position: absolute; top: -32px; left: -2px; z-index: 1; border-radius: 2px; box-shadow: 1px 2px 5px 0px rgb(0 0 0 / 20%); } .searchPackInput:placeholder-shown { top: 2px; left: 0px; padding: 8px 10px; box-shadow: 0px 0px 0px 0px rgb(0 0 0 / 0%); background: #eff2f5; } .searchPackContainer{ width: 220px; overflow: hidden; } .emoji_block_cont, .emoji_tabs_wrap { overflow: visible; } .emoji_tab_-2 { margin-left: 150px; } `; document.head.appendChild(document.createElement("style")).innerHTML = style; } (function injectScript() { const script = document.createElement('script'); const code = '(' + Main + ')();'; script.appendChild(document.createTextNode(code)); (document.body || document.head || document.documentElement).appendChild(script); })();