-
Сообщение ${author} #${post_id}
+
Сообщение ${author}#${post_id} (ссылка на пост)
Загрузка...
@@ -110,7 +113,7 @@ function openbc (e)
data = Base64.decode(response.data);
data = data.replace(
/
\[QUOTE=\"(.*?), post: (.*?), member: (.*?)\"\]<\/p>(.*?)
\[\/QUOTE\]<\/p>/ig,
- ""
+ ""
)
__('postmessage', ob).innerHTML = data;
diff --git a/assets/js/categories.js b/assets/js/categories.js
index a943ef0..8f7c2bc 100644
--- a/assets/js/categories.js
+++ b/assets/js/categories.js
@@ -98,7 +98,6 @@ function savePages (output)
( function (a) {
var el = JSON.parse(storageCache[a]);
- log(el.tab, tab);
if (el.tab == oldtab)
{
el.tab = tab;
@@ -120,7 +119,121 @@ function savePages (output)
});
}
-function userStyles()
+function userStyles ()
{
- set('userstyles-css', JSON.stringify(__('[userstyles]').value));
-}
\ No newline at end of file
+ set('userstyles-css', JSON.stringify(__('textarea[userstyles]').value));
+ __('style[userstyles]').innerHTML = __('textarea[userstyles]').value;
+
+ openAlert
+ ({
+ titleOf: 'Редактор стилей',
+ text: 'Стили изменены!'
+ });
+}
+
+const startScanning = function (event)
+{
+ var puth = '',
+ el = event.target,
+ style = getComputedStyle(el),
+
+ top = (parseInt(style.marginTop) - 1) + 'px',
+ right = (parseInt(style.marginRight) - 1) + 'px',
+ bottom = (parseInt(style.marginBottom) - 1) + 'px',
+ left = (parseInt(style.marginLeft) - 1) + 'px';
+
+ el.style.setProperty('border', '1px solid yellow', 'important');
+ el.style.setProperty('margin', `${top} ${right} ${bottom} ${left}`);
+
+ el.addEventListener
+ ('mouseout', function (event) {
+ var el = event.target;
+
+ el.style.removeProperty('border');
+ el.style.removeProperty('margin');
+ });
+
+ while (el.nodeName != 'BODY')
+ {
+ var classes = el.className.replace(/\s+/g, ' ').trim().split(' ').join('.');
+
+ while (classes.indexOf('..') > -1)
+ classes = classes.replace('..', '.');
+
+ if (classes.length == 0)
+ puth = `${el.nodeName} ${puth}`;
+
+ else
+ puth = `${el.nodeName}.${classes} ${puth}`;
+
+ el = el.parentElement;
+ }
+
+ __('bottomhelper').innerHTML = puth;
+}
+
+function animateClosing ()
+{
+ __('bottomhelper').style.setProperty('margin-top', '50px');
+ __('bottomhelper').style.setProperty('margin-left', '50%');
+ __('bottomhelper').style.setProperty('transform', 'translateX(-50%)');
+ __('bottomhelper').style.setProperty('width', 'auto');
+ __('bottomhelper').style.setProperty('text-align', 'center');
+ __('bottomhelper').style.setProperty('font-size', '13px');
+
+ setTimeout (() => {
+ __('bottomhelper').style.setProperty('opacity', '0');
+ __('bottomhelper').style.setProperty('margin-top', '0px');
+
+ setTimeout (() => {
+
+ __('bottomhelper').outerHTML = '';
+ }, 300);
+ }, 500);
+}
+
+function scanDom ()
+{
+ var bottomhelper = document.createElement('bottomhelper'),
+ body = document.body;
+
+ body.appendChild(bottomhelper);
+ body.addEventListener('mouseover', startScanning);
+
+ body.addEventListener
+ ('click', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ body.removeEventListener('mouseover', startScanning);
+ animateClosing();
+
+ this.removeEventListener('click', arguments.callee);
+ });
+}
+
+watching
+({
+ elem: 'textarea[userstyles]',
+
+ callback: function (el)
+ {
+ el.addEventListener
+ ('keydown', function (e) {
+ if(e.keyCode === 9)
+ {
+ e.preventDefault();
+
+ var start = this.selectionStart,
+ end = this.selectionEnd,
+
+ value = e.target.value,
+ before = value.substring(0, start),
+ after = value.substring(end);
+
+ e.target.value = `${before}\t${after}`;
+ this.selectionStart = this.selectionEnd = start + 1;
+ }
+ }, false);
+ }
+});
\ No newline at end of file
diff --git a/assets/js/chat.js b/assets/js/chat.js
index 0069699..3a073e6 100644
--- a/assets/js/chat.js
+++ b/assets/js/chat.js
@@ -29,7 +29,6 @@ function styleSet (name, value)
function toDefault ()
{
- log(this, this.parentElement);
var input = this.parentElement.querySelector('input'),
name = input.getAttribute('var');
@@ -43,7 +42,6 @@ function toDefault ()
function chatSetting ()
{
- log(this);
var name = this.getAttribute('caller');
set(name, this.checked);
diff --git a/assets/js/checkversion.js b/assets/js/checkversion.js
index f094cfa..b439467 100644
--- a/assets/js/checkversion.js
+++ b/assets/js/checkversion.js
@@ -1,17 +1,18 @@
-const version = '0.1.2.2';
+const version = '1.0.0.0';
// Если новая версия
if (get('version', true) != version)
{
if (!get('first', true))
{
- adoor('wellcome');
+ openWindow('wellcome');
- var qn = $_('wellcome qn', afp),
+ var qn = $_('wellcome qn', fullPageMain),
len = qn.length,
i = 0, timer = 0;
- function trytodoit () {
+ function trytodoit ()
+ {
if (i < 1)
{
qn[i].style.setProperty('max-height', '100px');
@@ -35,7 +36,7 @@ if (get('version', true) != version)
{
setTimeout
( function () {
- adoor('wellcome');
+ openWindow('wellcome');
set('first', 'est zhi', true);
set('version', version, true);
@@ -53,9 +54,18 @@ if (get('version', true) != version)
titleOf: `Обновление`,
text: `Новая версия ${version}! Что внутри?
- Подъехало 2 фикса. Первый - размер окна со смайлами выходил за пределы окна браузера, из-за чего невозможно было сохранять смайлы. Второй - пофикшена старая проблема с постоянным присвоением размера смайлу
- Для всего остального есть ченджлог в самой теме)
- Хорошего дня!`
+ Что же, это первое столь глобальное обновление, но расскажу только об одной функции, всё
+ остальное ждёт вас в самой теме (а там правда куча всего).
+ Добавлена самая ожидаемая функция - доступность смайлов на ЛЮБЫХ устройствах, будь то ваш ПК, рабочий
+ ноутбук, телефон или планшет.
+ Для работы с ним необходима лишь авторизация в Google в любом месте, будь то Почта, YouTube и
+ прочее. Если вы уже были авторизованы хотя бы в одном из сервисов Google, то расширение
+ автоматически приступит к работе. Так же необходима установка расширения на них, но это ты
+ и без меня понял)
Предсказываю вопрос - А ЗАЧЕМ?
+ Отвечаю - Google Apps Script выступает в роли бекенда, и чтобы работать с ним Google требует
+ авторизацию пользователя. Я упростил авторизацию, сделав все махинации через себя, но Google
+ необходимо быть увереным, что пользователь есть пользователь.
Давай, беги в темку читать обо
+ всём остальном!`
});
}
}
\ No newline at end of file
diff --git a/assets/js/database.js b/assets/js/database.js
new file mode 100644
index 0000000..70b9d96
--- /dev/null
+++ b/assets/js/database.js
@@ -0,0 +1,252 @@
+class datadocs
+{
+ constructor ({ database_name, username, password })
+ {
+ this.database_name = database_name;
+
+ this.username = get('docs-username', true) || undefined;
+ this.password = get('docs-password', true) || undefined;
+ }
+
+ saveSmiles ()
+ {
+ let date = Date.now();
+ set('lasttime', date);
+
+ return this.send ({
+ type: 'setsmiles',
+ username: this.username || get('docs-username', true),
+ password: this.password || get('docs-password', true) || get('docs-username', true),
+ text: get('a-dota2smile', true),
+ cath: get('cath', true),
+ date: date
+ });
+ }
+
+ getSmiles (name)
+ {
+ name = name || this.username || get('docs-username', true);
+
+ return this.send ({
+ type: 'getsmiles',
+ username: name
+ });
+ }
+
+ loadSmiles ()
+ {
+ this.getSmiles()
+ .then((res) => {
+ if (res.type == 'Успешно')
+ {
+ if (res.lasttime > JSON.parse(get('lasttime')))
+ {
+ log(`GetSmiles > ${res.type} > Смайлы на сервере новее, присваиваем себе`);
+ set('a-dota2smile', res.value, true);
+ set('cath', res.cath, true);
+ set('lasttime', res.lasttime);
+
+ document.location.reload();
+ }
+ else
+ {
+ log(`GetSmiles > ${res.type} > У вас самые свежие смайлы`);
+ }
+ }
+ else
+ {
+ log(`GetSmiles > ${res.type} > ${res.name}`);
+ }
+ });
+ }
+
+ registration ({ password })
+ {
+ if (!password)
+ return { type: 'Ошибка', name: 'Регистрация не удалась - не указан пароль' }
+
+ return this.send ({
+ type: 'register',
+ username: get('docs-username', true),
+ password: password
+ });
+ }
+
+ changePassword ({ old, to })
+ {
+ let incaps = this;
+
+ return this.send ({
+ type: 'changepassword',
+ username: get('docs-username', true),
+ oldpassword: old,
+ newpassword: to
+ })
+ .then((res) => {
+ if (res.type == 'Успешно')
+ {
+ log (`changePassword > ${res.type} > ${res.name}`);
+ set('docs-password', res.newpass, true);
+ incaps.password = res.newpass;
+
+ change('success', `changepassword ifpasschanged`, `${res.type} > ${res.name}`);
+ }
+ else if (res.caption == 'incorrectOldPassword')
+ {
+ if (!has('docs-password', true) || get('docs-username') == res.pass)
+ {
+ log (`changePassword > Забыли пароль? Напишите мне в личку > AdmAlexander`);
+ }
+
+ log (`changePassword > ${res.name}`);
+ change('failed', `changepassword ifpasschanged`, `${res.type} > ${res.name}`);
+ }
+
+ change('finally', `changepassword ifpasschanged`);
+ __('changepassword input[oldpass]').value = res.newpass;
+ __('changepassword input[newpass]').value = '';
+
+ return res;
+ });
+ }
+
+ stayPassword ({ password })
+ {
+ let incaps = this;
+
+ return this.send ({
+ type: 'staypassword',
+ username: get('docs-username', true),
+ password: password
+ })
+ .then((res) => {
+ console.log(res.type);
+
+ if (res.type == 'Успешно')
+ {
+ log (`stayPassword > ${res.type} > ${res.name}`);
+ set('docs-password', res.pass, true);
+ incaps.password = res.pass;
+
+ change('success', `staypassword ifpasschanged`, `${res.name}`);
+ __('staypassword input[thispass]').value = res.pass;
+ }
+ else if (res.caption == 'incorrectOldPassword')
+ {
+ log (`${res.type} > ${res.name}`);
+ change('failed', `staypassword ifpasschanged`, `${res.name}`);
+ };
+
+ change('finally', `staypassword bottom fing`);
+ return res;
+ });
+ }
+
+ firstInit ()
+ {
+ let incaps = this;
+
+ watching
+ ({
+ elem: 'div.userbar span.username',
+ callback: function (el)
+ {
+ set('docs-username', el.innerText, true);
+ incaps.username = el.innerText;
+
+ incaps.registration({ password: el.innerText })
+ .then (function (res) {
+ if (res.type == 'Успешно')
+ {
+ log (`Register > ${res.type} > Пользователь успешно зарегистрирован!`);
+ incaps.password = get('docs-username', true);
+ set('docs-password', get('docs-username', true), true);
+ }
+ else
+ {
+ log(`Register > ${res.type} > ${res.name}`);
+ }
+
+ incaps.loadSmiles();
+ });
+ }
+ });
+ }
+
+ send (p)
+ {
+ let url = `https://script.google.com/macros/s/${this.database_name}/exec`;
+
+ return fetch(url, {
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ method: "POST",
+ body: JSON.stringify(p)
+ })
+ .then(function (res) {
+ if (res.status)
+ {
+ let response = {};
+
+ switch (res.status)
+ {
+ case 200:
+ response = res.json();
+ break;
+
+ case 400:
+ response = { type: 'Ошибка', name: 'Некорректный запрос' }
+ break;
+
+ case 401:
+ case 407:
+ sendCall('google401');
+ response = { type: 'Ошибка', name: 'Необходима авторизация в Google!' }
+ break;
+
+ case 403:
+ response = { type: 'Ошибка', name: 'Нет доступа' }
+ break;
+
+ case 404:
+ case 410:
+ response = { type: 'Ошибка', name: 'Файл не найден' }
+ break;
+
+ case 408:
+ response = { type: 'Ошибка', name: 'Сервер не ответил' }
+ break;
+
+ case 414:
+ response = { type: 'Ошибка', name: 'Размер URL превышает разрешенный размер' }
+ break;
+
+ case 429:
+ response = { type: 'Ошибка', name: 'Слишком много запросов, выполнение отклонено' }
+ break;
+
+ case 500:
+ case 502:
+ case 503:
+ case 504:
+ case 520:
+ response = { type: 'Ошибка', name: 'Внутренняя ошибка сервера' }
+ break;
+
+ default:
+ response = { type: 'Ошибка', name: `${res.status}: незарегистрированная ошибка` }
+ break;
+ }
+
+ return response;
+ }
+ else
+ {
+ return { type: 'Ошибка', name: 'Ответ не получен' }
+ }
+ })
+ .catch(err => console.log(err));
+ }
+}
\ No newline at end of file
diff --git a/assets/js/footerfunctions.js b/assets/js/footerfunctions.js
index c1a799e..5ec8e41 100644
--- a/assets/js/footerfunctions.js
+++ b/assets/js/footerfunctions.js
@@ -1,3 +1,4 @@
+
/**
* Общие переменные
*/
@@ -43,6 +44,36 @@ var chess = 'a-dota2smile',
}
];
+/**
+ * Загрузка локальных файлов
+ *
+ * @param string url
+ *
+ * @return promise
+ */
+function upload (url)
+{
+ return fetch(getURL(url))
+ .then ( function (response) { return response.text() })
+ .then ( function (html) { return html });
+}
+
+/**
+ * Отправка запроса вызова ф-ии в background
+ *
+ * @param string url
+ *
+ * @return promise
+ */
+function sendCall (name, value)
+{
+ var cV = JSON.parse(get('callerVariable', true)),
+ value = JSON.stringify(value) || "{}";
+
+ cV[name] = value;
+ set('callerVariable', JSON.stringify(cV), true);
+}
+
/**
* Кастомный log
*
@@ -118,36 +149,56 @@ function has (item, a)
/**
* Загрузка разрешённых стилей и скриптов
*
- * @param string capt
+ * @param array capt
*/
function load (capt)
{
- var name = capt.split('.')[0],
- type = capt.split('.')[1],
- elem = type == 'css' ? 'style' : type == 'js' ? 'script' : 'user';
+ capt.forEach
+ (function (a) {
+ var name = a.split('.')[0],
+ type = a.split('.')[1],
+ elem = type == 'css' ? 'style' : type == 'js' ? 'script' : 'user';
- if (get(name) == 'false') return false;
- else set(name, 'true');
-
- if (capt.indexOf('.') > -1)
- {
- fetch(chrome.extension.getURL(`/assets/${type}/${name}.${type}`))
- .then(function(response){
- return response.text();
- })
- .then(function(html){
- createDom(elem, html);
- log(`${name}.${type} загружен успешно`);
- });
- }
- else
- {
- setTimeout
- ( () => {
- let html = JSON.parse(get(`${capt}-css`));
- createDom('style', html);
- });
- }
+ if (get(name) == 'false') return false;
+ else set(name, 'true');
+
+ if (a.indexOf('.') > -1)
+ {
+ fetch(chrome.extension.getURL(`/assets/${type}/${name}.${type}`))
+ .then(function(response){
+ return response.text();
+ })
+ .then(function(html){
+ createDom
+ ({
+ name: elem,
+ html: html,
+ bounty:
+ {
+ name: name,
+ value: true
+ }
+ });
+ });
+ }
+ else
+ {
+ setTimeout
+ ( () => {
+ let html = JSON.parse(get(`${a}-css`));
+ createDom
+ ({
+ name: 'style',
+ html: html,
+ bounty:
+ {
+ name: a,
+ value: ''
+ }
+ });
+ });
+ }
+ });
}
/**
@@ -197,12 +248,15 @@ function dom (html)
*
* @return HTMLElement
*/
-function createDom (elem, html)
+function createDom ({name, html, classes, bounty})
{
- var el = document.createElement(elem);
- el.innerHTML = html;
-
- document.head.appendChild(el);
+ var el = document.createElement(name);
+ el.innerHTML = html || '';
+
+ if (classes) el.classList = classes;
+ if (bounty) el.setAttribute(bounty.name, bounty.value);
+
+ document.head.appendChild(el);
}
/**
@@ -295,4 +349,32 @@ function _getStorage ()
storage = JSON.parse(storage);
return storage;
+}
+
+function change (type, name, value)
+{
+ switch (type)
+ {
+ case 'success':
+ __(name).innerText = `Успешно > ${value}`;
+ __(name).style.setProperty('background', '#00bfff', 'important');
+ break;
+
+ case 'failed':
+ __(name).innerText = `Ошибка > ${value}`;
+ __(name).style.setProperty('background', 'red', 'important');
+ break;
+
+ case 'init':
+ __(name.text).innerText = value;
+ __(name.text).style.setProperty('background', '#00bfff', 'important');
+ __(name.button).style.setProperty('height', '0px', 'important');
+ __(name.button).style.setProperty('opacity', '0', 'important');
+ break;
+
+ case 'finally':
+ __(name).style.setProperty('height', '27px', 'important');
+ __(name).style.setProperty('opacity', '1', 'important');
+ break;
+ }
}
\ No newline at end of file
diff --git a/assets/js/forumredactor.js b/assets/js/forumredactor.js
index b3ec32d..530fddb 100644
--- a/assets/js/forumredactor.js
+++ b/assets/js/forumredactor.js
@@ -5,6 +5,7 @@ function dist ()
{
var ob = this,
type = dtod(ob, 'button'),
+ middleContent = tinyMCE.activeEditor.selection.getContent({format : 'html'}),
before = '', context = '', after = '';
switch (type)
@@ -12,38 +13,41 @@ function dist ()
case 'code':
tinyExec
({
- before: `
`,
- context: tinyMCE.activeEditor.selection.getContent({format : 'html'}),
- after: `
`
+ before: `
`,
+ context: middleContent,
+ after: `
`
});
break;
case 'font-size':
- if (ob.tagName == 'SPAN')
- {
- ob.style.setProperty('font-size', dtod(ob, 'font-size'));
- smce(ob, 'style', ob.style.cssText);
- }
- else
- {
- var fontSize = dtod(ob, 'font-size');
-
- tinyExec
- ({
- before: `
`,
- context: tinyMCE.activeEditor.selection.getContent({format : 'html'}),
- after: ``
- });
- }
+ var fontSize = dtod(ob, 'font-size');
+
+ var dol = document.createElement('div');
+ dol.innerHTML = middleContent;
+
+ $_('span', dol).forEach((a) => {
+ if (a.style.hasOwnProperty('font-size'))
+ a.style.removeProperty('font-size');
+ });
+
+ tinyExec
+ ({
+ before: `
`,
+ context: dol.innerHTML,
+ after: ``
+ });
+ delete dol;
break;
+
case 'font-background':
if (ob.tagName == 'SPAN')
{
- ob.style.setProperty('padding', '0 2px');
+ console.log(this);
ob.style.setProperty('background', '#989899');
ob.style.setProperty('color', '#1b1c20');
-
+ console.log(ob);
+
smce(ob, 'style', ob.style.cssText);
}
else
@@ -53,13 +57,15 @@ function dist ()
tinyExec
({
before: `
`,
- context: tinyMCE.activeEditor.selection.getContent({format : 'html'}),
+ context: ` ${middleContent} `,
after: ``
});
}
break;
}
+
+ console.log(ob);
}
/**
@@ -246,9 +252,9 @@ if (tinyMods.indexOf(mode) > -1)
("mouseenter", function (event) {
var ob = this,
title = ob.getAttribute('dota-title'),
- mcet = document.querySelector('div.mce-tooltip');
-
- log(event, this);
+ mcet = document.querySelector('div.mce-tooltip'),
+ clientRect = el.getBoundingClientRect().top,
+ top = window.scrollY + clientRect + el.clientHeight;
if (!mcet)
{
@@ -264,6 +270,7 @@ if (tinyMods.indexOf(mode) > -1)
mcet.querySelector('.mce-tooltip-inner').innerText = title;
mcet.style.setProperty('display', 'block');
mcet.style.setProperty('left', ((parseInt(el.offsetLeft) + 204) - (parseInt(mcet.offsetWidth))/2 + (parseInt(el.offsetWidth)/2)) + "px");
+ mcet.style.setProperty('top', `${top}px`)
});
el.addEventListener
diff --git a/assets/js/integrate.js b/assets/js/integrate.js
index 31a95ae..68f8d1d 100644
--- a/assets/js/integrate.js
+++ b/assets/js/integrate.js
@@ -1,23 +1,24 @@
/**
* Все основные переменные для удобства
*/
-var afp = __('fullpage'),
- smileSett = __('smiles category', afp),
- smileList = __('smile-list', afp),
- reservetime = __('asett pages[name="reserve"] reservetime', afp),
- mainsetting = $_('asett pages[name="mainsetting"] page', afp),
- asspages = $_('asett pages[name="pagesetting"] page', afp),
- asstabes = __('asett pages[name="tabsetting"]', afp),
- assscroll = __('asett pages[name="scrollbar"]', afp),
- asschat = __('asettchat pages[name="st"]', afp),
+var fullPageMain = __('fullpage'),
+ smileSett = __('smiles category', fullPageMain),
+ smileList = __('smile-list', fullPageMain),
+ reservetime = __('asett pages[name="reserve"] reservetime', fullPageMain),
+ mainsetting = $_('asett pages[name="mainsetting"] page', fullPageMain),
+ asspages = $_('asett pages[name="pagesetting"] page', fullPageMain),
+ asstabes = __('asett pages[name="tabsetting"]', fullPageMain),
+ assscroll = __('asett pages[name="scrollbar"]', fullPageMain),
+ asschat = __('asettchat pages[name="st"]', fullPageMain),
getchat = get('chat'),
storagePage = JSON.parse(get('page', true)),
cath = JSON.parse(get('cath', true)),
- alert = __('alert', afp), aflag = true;
+ alert = __('alert', fullPageMain), aflag = true;
/*
Отображение сообщений
*/
+
if (mode == 'unknown' && __('head title').innerText == 'Форум Dota 2' && (getchat == 'true' || getchat == null))
{
setInterval
@@ -435,7 +436,7 @@ if (mode == 'unknown' && __('head title').innerText == 'Форум Dota 2' && (g
chatTitle.appendChild
(dom(
- `
`
+ `
`
));
var red = (has('chatTurn')) ? '' : ' red';
@@ -458,6 +459,26 @@ function reload ()
input.checked = (get(input.value) == 'true');
});
+
+ watching
+ ({
+ elem: 'input[oldpass]',
+
+ callback: function (el)
+ {
+ el.value = has('docs-password', true) ? get('docs-password', true) : get('docs-username', true);
+ }
+ });
+
+ watching
+ ({
+ elem: 'input[thispass]',
+
+ callback: function (el)
+ {
+ el.value = has('docs-password', true) ? get('docs-password', true) : get('docs-username', true);
+ }
+ });
if (has('pages', true))
remove('pages', true);
@@ -468,7 +489,7 @@ function reload ()
storagePage = JSON.parse(get('page', true));
}
- __('[userstyles]').value = JSON.parse(get('userstyles-css')) || ``;
+ __('textarea[userstyles]').value = JSON.parse(get('userstyles-css')) || ``;
// Переприсваиваем все разрешённые вкладки смайлов
asspages.forEach
@@ -497,7 +518,6 @@ function reload ()
Object.keys(cath).forEach
(function (tab) {
tab = cath[tab];
- log(tab, tab.name, tab.index);
arraytabes.push({ name: tab.name, index: tab.index, hidden: tab.hidden });
@@ -552,8 +572,6 @@ function reload ()
chess = 'a-dota2smile';
save();
- log(_getStorage);
-
document.location.reload();
return false;
}
diff --git a/assets/js/reservecopy.js b/assets/js/reservecopy.js
index cfebedd..da1ea24 100644
--- a/assets/js/reservecopy.js
+++ b/assets/js/reservecopy.js
@@ -112,12 +112,6 @@ const reserve =
set(a, reserve.get(`reserve-${a}`), true);
});
- if (has('a-dota2smile', true))
- {
- set('a-dota2smile', '{}', true);
- set('reserve-a-dota2smile', '{}', true);
- }
-
openAlert
({
titleOf: 'Резервная копия',
@@ -153,6 +147,12 @@ const reserve =
remove(`reserve-${a}`, true);
});
+ if (has('a-dota2smile', true))
+ {
+ set('a-dota2smile', '{}', true);
+ set('reserve-a-dota2smile', '{}', true);
+ }
+
remove('reserve-time', true);
openAlert
diff --git a/assets/js/setting.js b/assets/js/setting.js
new file mode 100644
index 0000000..c8e5313
--- /dev/null
+++ b/assets/js/setting.js
@@ -0,0 +1,17 @@
+ let htmlSettingNames =
+[
+ { name: 'smiles', position : 'first' },
+
+ { name: 'asett', position : 'second' },
+ { name: 'asettchat', position : 'second' },
+ { name: 'chan', position : 'second' },
+
+ { name: 'savetouser', position : 'third' },
+ { name: 'wellcome', position : 'third' },
+ { name: 'userstyles', position : 'third' },
+ { name: 'changepassword', position : 'third' },
+ { name: 'staypassword', position : 'third' },
+
+ { name: 'alert', position : 'last' }
+],
+htmlCountNames = htmlSettingNames.length;
\ No newline at end of file
diff --git a/assets/js/smiles.js b/assets/js/smiles.js
index c6e4883..d1f9747 100644
--- a/assets/js/smiles.js
+++ b/assets/js/smiles.js
@@ -136,7 +136,7 @@ function ch (name)
__('bottom fing', cha).setAttribute('onclick', `chan('${name}')`);
- adoor('chan');
+ openWindow('chan');
}
/**
@@ -229,6 +229,8 @@ function save ()
storageCache = _getStorage();
reload();
+
+ sendCall('saveSmiles');
openAlert({text: 'Ваши смайлы сохранены!'});
}
@@ -254,113 +256,98 @@ function lastOf (obj)
}
/**
- * Отображение списка смайлов для того, чтобы поделиться с кем-либо
+ * Объединение двух массивов с объектами
*/
-function saveTo ()
+function collapseObjects (array)
{
- save();
- __('fullpage saveTo textarea').value = JSON.stringify( _getStorage() );
+ let a = array[0],
+ b = array[1];
+
+ for (name in a)
+ {
+ if (b[name] === undefined)
+ {
+ b[name] = a[name];
+ }
+ }
+
+ return b;
+}
+
+function collapseMassives (array)
+{
+ return array[0].concat(array[1].filter((one) => {
+ return !array[0].find((el) => el.name === one.name);
+ }))
}
/**
- * Подгрузка смайлов с пака пользователя к своим смайлам
+ * Проверка пользователя на существование + подгрузка смайлов
*/
-function loadFrom (bool)
+function findUser ()
{
- // Будет обидно, если изменения не сохранятся, верно?)
- save();
-
- var area = (bool)? __('blockquote.messageText .quoteContainer p')
- : __('fullpage loadfrom textarea'),
-
- your = (typeof storageCache == 'string')? JSON.parse(storageCache) : storageCache,
- load = (bool)? ((typeof area.innerText == 'string')? JSON.parse(area.innerText) : area.innerText)
- : ((typeof area.value == 'string')? JSON.parse(area.value) : area.value),
-
- oth = Object.assign(load, your);
-
- set(chess, JSON.stringify(oth), true);
- area.value = '';
-
- // Ну и сразу получаем готовенькое
- storageCache = _getStorage();
- reload();
+ var main = __('savetouser'),
+ info = __('information', main),
+ username = __('input[username]', main).value;
- save();
+ info.innerHTML = 'Загрузка..';
- openAlert({text: 'Смайлы загружены!'});
+ sendCall('findUsersmiles', {
+ username: __('input', main).value
+ });
}
/**
- * Автоматически поделиться с указанным пользователем
+ * Подгрузка смайлов - объединение и сохранение
*/
-function sendSmiles ({you, to, username})
+function saveLoadedSmiles ()
{
- var you = you, user = to, username = username,
- title = `[d2s] ${you} => ${username}`,
- content =
- `
У вас не установлено расширение для использования кастомных смайлов
Для продолжения проследуйте сюда.
-
-
- ${JSON.stringify( _getStorage() )}
-
-
`;
-
- void requestHandler.ajaxRequest
- ("/api/message/createConversation",
- { title: title, content: content, recipient: user },
-
- function (response)
- {
- if (response.status == 'success')
- {
- openAlert
- ({
- titleOf: 'Работа со смайлами',
- text: 'Пак смайлов отправлен!'
- });
-
- adoor('savetouser');
- adoor('saveto');
- }
- else
- {
- openAlert({text: 'Ошибка'});
- log(response);
- }
- }
- )
+ var main = __('savetouser'),
+ obj = __('information[savetouser]', main),
+ bottom = __('bottom', main),
+ smiles = JSON.parse(__('input[smiles]', main).value),
+ cath = JSON.parse(__('input[cath]', main).value),
+ newSmiles = collapseObjects ([smiles, storageCache]),
+ newCath = collapseMassives ([JSON.parse(get('cath', true)), cath]);
+
+ set('cath', JSON.stringify(newCath), true);
+
+ set(chess, JSON.stringify(newSmiles), true);
+ storageCache = _getStorage();
+
+ reload();
+
+ openWindow('savetouser');
+
+ bottom.innerHTML = '';
+ obj.innerHTML = '';
+
+ openAlert({text: 'Смайлы пользователя добавлены к вашим!'});
}
-/**
- * Проверка пользователя на существование
- */
-function findUser ()
+function changePassword ()
{
- var stu = __('fullpage savetouser'),
- info = __('information', stu),
- username = __('input', stu).value;
-
- info.innerHTML = 'Загрузка..';
-
- fetch(`https://dota2.ru/forum/search?type=user&keywords=${username}&sort_by=username`)
- .then(function(response){
- return response.text();
- })
- .then(function(html){
- var you = __('div.hello .username').innerHTML,
- userdocument = __('.member-list-item .avatar', dom(html).ownerDocument),
- href = userdocument.href.split('/'),
- id = href[href.length - 2].split('.')[1],
- avatar = __('img', userdocument).src;
-
- info.innerHTML =
- `
-
- Имя ${username}
- ID ${id}
- При подтверждении ниже будет создана переписка с пользователем, где ему будут предоставлены смайлы и кнопка, при нажатии на которую он сможет добавить смайлы себе. Вы уверены, что это тот самый пользователь?
- Да, отправить
- `;
- });
+ let v = 'changepassword';
+
+ change('init', { text: `${v} ifpasschanged`, button: `${v} bottom fing` },
+ 'Идёт отправка запроса на смену пароля'
+ );
+
+ sendCall('changePassword', {
+ old: __('input[oldpass]').value,
+ to: __('input[newpass]').value
+ });
+}
+
+function stayPassword ()
+{
+ let v = 'staypassword';
+
+ change('init', { text: `${v} ifpasschanged`, button: `${v} bottom fing` },
+ 'Проверка правильности пароля'
+ );
+
+ sendCall('stayPassword', {
+ pass: __('input[thispass]').value
+ });
}
\ No newline at end of file
diff --git a/extens.css b/extens.css
index 4a4fe73..2963fe0 100644
--- a/extens.css
+++ b/extens.css
@@ -1,5 +1,11 @@
/* Стили */
+:root
+{
+ --top-color: #2b2c32;
+ --hover-top-color: #514f4f;
+}
+
.smile-content
{
display: inline-block!important;
@@ -20,7 +26,12 @@
.node .content-info
{
- overflow: inherit!important;
+ overflow: hidden;
+}
+
+.content-list .content-list .node .content-info
+{
+ overflow: visible!important;
}
fullpage
@@ -44,8 +55,7 @@ fullpage
margin-top: -1000%;
}
-fullpage
-{ z-index: 10000; }
+fullpage { z-index: 10000; }
backfon
@@ -54,7 +64,6 @@ backfon
height: 100%;
position: fixed;
- z-index: 10001;
background: rgba(0, 0, 0, .7);
transition: opacity .3s;
@@ -62,42 +71,17 @@ backfon
opacity: 0;
}
-backfon.loadfrom, backfon.saveto,
-backfon.asett, backfon.asettchat, backfon.chan
-{
- margin-top: -1000%;
- z-index: 10003;
-}
-
-backfon.alert, backfon.savetouser, backfon.wellcome,
-backfon.userstyles
-{
- margin-top: -1000%;
- z-index: 10005;
-}
+[backfirst] { margin-top: -1000%; z-index: 10001; }
+[backsecond] { margin-top: -1000%; z-index: 10003; }
+[backthird] { margin-top: -1000%; z-index: 10005; }
+[backlast] { margin-top: -1000%; z-index: 10099; }
fullpage *
{
display: flex;
}
-fullpage.open, smiles.open,
-loadfrom.open, saveto.open, savetouser.open,
-alert.open, asett.open, asettchat.open, backfon.open,
-chan.open, wellcome.open, userstyles.open
-{
- opacity: 1;
-}
-
-fullpage.margin, smiles.margin,
-loadfrom.margin, saveto.margin, savetouser.margin,
-alert.margin, asett.margin, asettchat.margin, backfon.margin,
-chan.margin, wellcome.margin, userstyles.margin
-{
- margin-top: 0;
-}
-
-smiles, loadfrom, saveto, savetouser, asett, asettchat, alert, chan, wellcome, userstyles
+fullpage > *:not(backfon)
{
position: absolute;
@@ -114,13 +98,24 @@ smiles, loadfrom, saveto, savetouser, asett, asettchat, alert, chan, wellcome, u
opacity: 0;
}
-smiles { margin-top: -1000%; z-index: 10002; }
-loadfrom, saveto, asett, asettchat, chan { margin-top: -1000%; z-index: 10004; }
-alert, savetouser, wellcome, userstyles { margin-top: -1000%; z-index: 10006; }
+fullpage.open, fullpage > *.open
+{
+ opacity: 1;
+}
+
+fullpage.margin, fullpage > *.margin
+{
+ margin-top: 0;
+}
+
+[first] { margin-top: -1000%; z-index: 10002; }
+[second] { margin-top: -1000%; z-index: 10004; }
+[third] { margin-top: -1000%; z-index: 10006; }
+[last] { margin-top: -1000%; z-index: 10100; }
fullpage top
{
- background: #2b2c32;
+ background: var(--top-color);
border-radius: 3px;
margin: 6px;
@@ -141,7 +136,7 @@ fullpage close, fullpage remove
fullpage middle
{
- height: 100%;
+ height: auto;
flex-direction: column;
padding: 10px 16px;
@@ -149,7 +144,7 @@ fullpage middle
@media (max-width: 600px)
{
- smiles, loadfrom, saveto, asett, asettchat, chan, userstyles
+ smiles, changepassword, asett, asettchat, chan, userstyles
{
width: 100%;
height: 100%;
@@ -176,6 +171,7 @@ fullpage pages
padding: 10px 16px;
justify-content: space-between;
flex-flow: row wrap;
+ font-size: 12px;
}
pages page
@@ -185,20 +181,25 @@ pages page
padding: 0px 9px;
margin: 3px;
border-radius: 3px;
- background: #2b2c32;
+ background: var(--top-color);
justify-content: center;
align-items: center;
+ font-size: 11px;
+}
+
+pages page[onclick]
+{
+ cursor: pointer;
+}
+
+pages page[onclick]:hover
+{
+ background: var(--hover-top-color);
}
pages page.fullstroke
{
width: 100%;
- padding: 0px 9px;
- margin: 3px;
- border-radius: 3px;
- background: #2b2c32;
- justify-content: center;
- align-items: center;
}
.fullstroke gotcha
@@ -277,8 +278,15 @@ fing
background-color: #000!important;
padding: 0px 7px!important;
border: 1px solid #343434!important;
-
+ opacity: 1;
+
cursor: pointer;
+ transition: all .3s;
+}
+
+fing[not-overflow]
+{
+ overflow: hidden;
}
fing:hover
@@ -316,7 +324,7 @@ fullpage pass t
padding: 3px 9px;
border-radius: 3px;
margin: 3px 6px 3px 0;
- background: #2b2c32;
+ background: var(--top-color);
}
fullpage pass confirmation
@@ -334,6 +342,7 @@ fullpage pass fing
smile-list
{
flex-direction: column;
+ padding-right: 6px;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
@@ -366,7 +375,7 @@ smile-list tab list:before
width: 1px;
height: 41px;
- background: #2b2c32;
+ background: var(--top-color);
position: absolute;
}
@@ -380,7 +389,7 @@ smile-list tab list:last-child:before
width: 1px;
height: 23px;
- background: #2b2c32;
+ background: var(--top-color);
position: absolute;
}
@@ -395,7 +404,7 @@ smile-list tab list:after
width: 10px;
height: 1px;
- background: #2b2c32;
+ background: var(--top-color);
position: absolute;
}
@@ -702,7 +711,140 @@ page p {
{
border: 1px solid #333;
background: #3333;
+
color: #eee!important;
line-height: 18px!important;
font-size: 12px;
+}
+
+bottomhelper
+{
+ position: fixed;
+ top: 0;
+ width: 100%;
+
+ background: #1d1d1d;
+ padding: 3px;
+
+ color: #eee;
+ font-size: 10px;
+ z-index: 10011;
+ opacity: 1;
+
+ transition: all .3s;
+}
+
+bottomhelper span
+{
+ font-size: 9px;
+ color: #ccc;
+}
+
+information.taked
+{
+ background: #00bfff;
+ border-radius: 6px;
+ padding: 8px;
+ color: #fff;
+ justify-content: center;
+ margin-bottom: 6px;
+ cursor: pointer;
+}
+
+information[savetouser]
+{
+ flex-direction: column;
+}
+
+smilepreview
+{
+ display: flex;
+ align-content: space-evenly;
+ justify-content: space-evenly;
+ flex-flow: row wrap;
+}
+
+smilepreview sp
+{
+ width: 30px;
+ height: 60px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ margin: 4px 20px;
+}
+
+smilepreview sp bgnd
+{
+ width: 30px;
+ height: 30px;
+ background-size: contain !important;
+ background-repeat: no-repeat !important;
+ background-position: center center !important;
+}
+
+smilepreview sp ttl {
+ font-size: 11px;
+ overflow: hidden;
+}
+
+savetouser middle
+{
+ overflow-y: scroll;
+ max-height: calc(100vh - 100px);
+}
+
+changepassword ifpasschanged,
+staypassword ifpasschanged
+{
+ border-radius: 6px;
+ color: #fff;
+ justify-content: center;
+ margin-bottom: 6px;
+ height: auto;
+
+ font-size: 11px;
+
+ transition: all .3s;
+}
+
+changepassword ifpasschanged:not(:empty),
+staypassword ifpasschanged:not(:empty)
+{
+ max-height: 100px;
+ padding: 8px;
+ background: #00bfff;
+}
+
+changepassword ifpasschanged:empty,
+staypassword ifpasschanged:empty
+{
+ max-height: 0px;
+ padding: 0px 8px;
+ background: #121215;
+}
+
+flex[row]
+{
+ flex-direction: row;
+ align-items: center;
+ margin: 4px 0px;
+ padding: 2px 6px;
+ background: #2b2c32;
+ border-radius: 6px;
+}
+
+changepassword label[for],
+staypassword label[for]
+{
+ flex: 1;
+}
+
+changepassword input,
+staypassword input
+{
+ flex: 2;
+ padding: 0px 10px;
+ border-color: #282727!important;
+ background: #121215!important;
}
\ No newline at end of file
diff --git a/extension.js b/extension.js
index 8bba7a5..50643f4 100644
--- a/extension.js
+++ b/extension.js
@@ -1,35 +1,40 @@
/**
* Загрузка разрешённых стилей и скриптов
*/
-
-/* Скрипты */
-load ('footerfunctions.js');
-load ('queryfinder.js');
-load ('reservecopy.js');
-load ('smiles.js');
-load ('categories.js');
-load ('alert.js');
-
-/* Форумные сообщения */
-if (forumpostMods.indexOf(mode) > -1)
-{
- load ('forumpost.css');
- load ('forumpost.js');
-}
+load
+([
+ 'footerfunctions.js', // Основные ф-ии для работы расширения
+ 'queryfinder.js', // Упрощенный querySelector/all
+
+ 'reservecopy.js', // Модуль - резервная копия
+ 'smiles.js', // Модуль - смайлы
+ 'categories.js', // Модуль - категории
+ 'alert.js' // Модуль - уведомления
+])
/* Хлебные крошки */
-if (mode == 'threads')
+if (mode == 'threads') // Только форум
{
- load ('breadcrumb.css');
- load ('breadcrumb.js');
+ load
+ ([
+ 'breadcrumb.css',
+ 'breadcrumb.js'
+ ]);
}
-/* Форумный редактор */
-load ('forumredactor.css');
-load ('forumredactor.js');
+if (tinyMods.indexOf(mode) > -1)
+ load
+ ([
+ // Форумные сообщения
+ 'forumpost.css', 'forumpost.js',
+ // Форумный редактор
+ 'forumredactor.css', 'forumredactor.js',
+ // Стили "Фикс сообщений на мобильном"
+ 'mobileforumfix.css'
+ ]);
/* Стили пользователя */
-load ('userstyles');
+load ([ 'userstyles' ]);
/* Чат на главной */
watching
@@ -40,8 +45,7 @@ watching
{
if (mode == 'unknown' && document.querySelector('head title').innerHTML == 'Форум Dota 2')
{
- load ('chat.css');
- load ('chat.js');
+ load ([ 'chat.css', 'chat.js' ]);
}
}
});
@@ -49,12 +53,162 @@ watching
/**
* Начало
*/
-
document.addEventListener
("DOMContentLoaded", () => {
var index = -2, button, tabs, name_title = 'Собственные',
- reloadInterval = setInterval(reload, 3000);
-
+ reloadInterval = setInterval(reload, 3000), winn = null;
+
+ const User = new datadocs ({
+ database_name: 'AKfycbyc5hHlcmND6XnrguiI4uegok1yAd2Mf78z5NzgfQ4uqN0TxpOo'
+ });
+
+ if (get('docs-username', true) != null)
+ {
+ User.username = get('docs-username', true);
+ User.password = has('docs-password', true) ? get('docs-password', true)
+ : get('docs-username', true);
+
+ User.loadSmiles();
+ }
+ else
+ {
+ User.firstInit();
+ }
+
+ function takeCall ()
+ {
+ let cV = JSON.parse(get('callerVariable', true)) || {};
+
+ for (arg in cV)
+ {
+ switch (arg)
+ {
+ case 'getSmiles':
+ let name = JSON.parse(cV[arg]).username || get('docs-username') || null;
+
+ if (name != null || name != undefined)
+ User.getSmiles(name).then(res => log(`getSmiles > ${res.type} > ${res.name}`));
+ else User.getSmiles().then(res => log(`getSmiles > ${res.type} > ${res.name}`));
+
+ break;
+
+ case 'saveSmiles':
+ User.saveSmiles()
+ .then(res => log(`saveSmiles > ${res.type} > ${res.name}`));
+ break;
+
+ case 'changePassword':
+ let oldpassword = JSON.parse(cV[arg]).old,
+ newpassword = JSON.parse(cV[arg]).to;
+
+ User.changePassword({
+ old: oldpassword,
+ to: newpassword
+ });
+ break;
+
+ case 'stayPassword':
+ let password = JSON.parse(cV[arg]).pass;
+
+ User.stayPassword({
+ password: password
+ });
+ break;
+
+ case 'registration':
+ let thispassword = JSON.parse(cV[arg]).password;
+
+ User.registration({
+ password: thispassword
+ })
+ .then ( function (res) {
+ if (res.type == 'Успешно')
+ {
+ User.password = password;
+ set('docs-password', password, true);
+
+ log('registration > Регистрация прошла успешно');
+ }
+ });
+
+ break;
+
+ case 'google401':
+ watching
+ ({
+ elem: 'information[smiles]',
+
+ callback: function (el)
+ {
+ el.innerText = 'Необходима авторизация в Google для синхронизации!';
+ el.classList.add('taked');
+ el.setAttribute('onclick', "sendCall('authorize')");
+ }
+ });
+
+ break;
+
+ case 'authorize':
+ winn = window.open(
+ `https://script.google.com/macros/s/${User.database_name}/exec`,
+ 'window', "width=500px, height=400px, left=100px, top=100px"
+ );
+
+ break;
+
+ case 'findUsersmiles':
+ User.getSmiles(JSON.parse(cV[arg]).username)
+ .then ((res) => {
+ if (res.type == 'Успешно')
+ {
+ let main = __('savetouser'),
+ obj = __('information[savetouser]', main),
+ bottom = __('bottom', main),
+ div = document.createElement('div'),
+ smiles = JSON.parse(res.value),
+ coll, smilesDom = dom('
');
+
+ for (smile in smiles)
+ {
+ let link = JSON.parse(smiles[smile]).src;
+
+ smilesDom.appendChild(dom(`
+
+
+ ${smile}
+
+ `));
+ }
+
+ bottom.innerHTML = '';
+ bottom.appendChild(dom(`
Сохранить`));
+
+ obj.innerHTML = '';
+ obj.appendChild(smilesDom);
+
+ __('input[smiles]', main).value = res.value;
+ __('input[cath]', main).value = res.cath;
+ }
+ else
+ {
+ log('sendCall > findUsersmiles > Несуществующий пользователь')
+ }
+ });
+
+ break;
+
+ default:
+ log('sendCall > Несуществующий тип запроса');
+ break;
+ }
+
+ delete cV[arg];
+ }
+
+ set('callerVariable', JSON.stringify(cV), true);
+ }
+
+ let callInterval = setInterval(takeCall, 500);
if (mode == 'conversation')
{
@@ -68,8 +222,8 @@ document.addEventListener
butt.querySelector('p').outerHTML = '';
butt.appendChild
(dom(
- `
- Активировать себе
+ `
+ Функция более недоступна, для добавления смайлов достаточно ввести никнейм
`
));
}
@@ -120,32 +274,51 @@ document.addEventListener
/**
* Шаг нулевой - определение страницы настроек
*/
- fetch(getURL('/assets/settings.html'))
- .then(function(response){
- return response.text();
- })
- .then(function(html){
- html = dom(html);
-
- document.body.insertBefore(html, document.body.firstChild);
-
- watching
- ({
- elem: 'div.userbar',
- callback: function (el)
- {
- el.insertBefore( dom(`
-
-
-
- `), el.querySelector('a[title="Сообщения"]'));
-
- load ('integrate.js');
- load ('checkversion.js');
- }
- });
- });
+ let htmlResult = '',
+ htmlCount = 0,
+ htmlInterval = setInterval
+ (function () {
+ if (htmlCount === htmlCountNames)
+ {
+ document.body.insertBefore
+ (
+ dom(`${htmlResult}`),
+ document.body.firstChild
+ );
+
+ watching
+ ({
+ elem: 'div.userbar',
+ callback: function (el)
+ {
+ el.insertBefore( dom(`
+
+
+
+ `), el.querySelector('a[title="Сообщения"]'));
+ load ([ 'integrate.js', 'checkversion.js' ]);
+ }
+ });
+
+ clearInterval (htmlInterval);
+ }
+ }, 200);
+
+ htmlSettingNames.forEach
+ (function(a) {
+ upload(`/assets/html/${a.name}.html`)
+ .then( function (tmp) {
+ htmlResult +=
+ `
+ <${a.name} ${a.position}>
+ ${tmp}
+ ${a.name}>`;
+
+ htmlCount++;
+ });
+ });
+
/**
* Если tinyMCE есть на страницах, то продолжить
*/
diff --git a/manifest.json b/manifest.json
index 4288235..a47c105 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,6 +1,6 @@
{
"manifest_version": 2,
- "version": "0.1.2.2",
+ "version": "1.0.0.0",
"name": "D2S - форумный редактор",
"description": "Кастомные смайлы, новый чат, редактор текста и прочее!",
@@ -8,12 +8,18 @@
"css": [ "extens.css" ],
"js":
[
+ "assets/js/setting.js",
+ "assets/js/queryfinder.js",
"assets/js/footerfunctions.js",
+ "assets/js/database.js",
"extension.js"
],
"matches": [ "*://dota2.ru/forum*" ],
"run_at": "document_start"
} ],
+ "permissions": [
+ "*://*/"
+ ],
"icons": {
"128": "assets/images/favicon_128.png",
"16": "assets/images/favicon_16.png",