gro-ove / TJ User Tagging

// ==UserScript==
// @name        TJ User Tagging
// @namespace   Violentmonkey Scripts
// @match       https://tjournal.ru/*
// @grant       none
// @version     1.12
// @license     MIT
// @author      -
// @description 3/29/2020, 5:46:18 PM
// @grant   GM_getValue
// @grant   GM_setValue
// @grant   GM_addValueChangeListener
// ==/UserScript==

let tags = {};

function save(){
  GM_setValue('tags', JSON.stringify(tags, (k, v) => v ? v : void 0));
  tagsUpdate();
}

function setTag(userId, targetNode) {
  let oldColor = '#' + ((tags[userId] ? tags[userId].split('#')[1] : null) || '888888');
  let newTag = prompt('Тег, или тег#цвет:', tags[userId] ? tags[userId].split('#')[0] : '');
  if (newTag == null) return;
  
  Object.assign(tags, { [userId]: newTag });
  save();
  
  if (newTag && newTag.indexOf('#') === -1){
    let colorPicker = document.body.appendChild(document.createElement('input'));
    let rect = targetNode ? targetNode.getBoundingClientRect() : { x: 32, y: 32 };
    colorPicker.type = 'color';
    colorPicker.value = oldColor;
    colorPicker.style.width = '0px';
    colorPicker.style.height = '0px';
    colorPicker.style.position = 'fixed';
    colorPicker.style.left = `${rect.x - 8}px`;
    colorPicker.style.top = `${rect.y - 8}px`;
    onchange = function(){
      Object.assign(tags, { [userId]: newTag + colorPicker.value });
      save();
      document.body.removeChild(this);
    };
    setTimeout(() => colorPicker.click(), 10);
  }
}

function svgIcon(){
  return `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><path d="M458.667,0H323.349c-25.643,0-49.771,9.984-67.904,28.117L18.197,265.387C6.635,276.949,0,292.949,0,309.376 c0,16.341,6.635,32.341,18.197,43.904l140.544,140.544C170.283,505.365,186.283,512,202.709,512 c16.341,0,32.341-6.635,43.904-18.197l237.269-237.269C502.016,238.421,512,214.293,512,188.651V53.333 C512,23.915,488.085,0,458.667,0z M394.667,170.667c-29.419,0-53.333-23.915-53.333-53.333c0-29.419,23.915-53.333,53.333-53.333 S448,87.915,448,117.333C448,146.752,424.085,170.667,394.667,170.667z"/></svg>`;
}

function addTagButton() {
  let target = document.querySelector('.etc_control[data-subsite-url]');
  if (target && !document.querySelector('._tg')) {
    with (target.insertAdjacentElement('beforebegin', document.createElement('div'))) {
      onclick = function(){ /\/(\d+)-/.test(location.href) && setTag(RegExp.$1, this); };
      className = '_tg v-button v-button--default v-button--size-default';
      innerHTML = `<div class="v-button__icon">${svgIcon()}</div><span class="v-button__label"></span>`
    }
  }
  setTimeout(addTagButton, 500);
}

function isColorDark(color) {
  return !color || (color.length == 6 ? parseInt(color.substr(2, 2), 16) : parseInt(color[1], 16) * 16) < 200;
}

function tagsUpdate() {
  (window._tgStyle || (window._tgStyle = document.body.appendChild(document.createElement('style')))).innerHTML = `
  .user_name:after, .content-header-author:after, .vote__users__item .vote__users__item__name:after, .live__item__user:after { 
    display:inline-block; padding:3px 4px 2px 4px; margin:-2px 4px -3px 4px; border-radius:2px; font-weight:normal; font-size:small; 
  }
  .vote__users__item .vote__users__item__name:after { 
    padding:0 4px 0 4px; margin:-2px 4px -3px 4px;
  }
  .v-subscribe-button[data-subsite-id] ~ ._tg { 
    cursor:pointer; position: relative;
  }
  .v-subscribe-button[data-subsite-id] ~ ._tg span:after { 
    content:"Тег"; 
  }
  ` + Object.keys(tags).filter(x => tags[x]).map(x => 
    `a[href*="/${x}-"] .user_name:after, 
    .vote__users__item[href*="/${x}-"] .vote__users__item__name:after, 
    .content-header-author[href*="/${x}-"]:after, 
    .live__item__user[href*="/${x}-"]:after, 
    .v-subscribe-button[data-subsite-id="${x}"] ~ ._tg,
    .v-subscribe-button[data-subsite-id="${x}"] ~ ._tg span:after { 
      content: "${tags[x].split('#')[0]}"; 
      background: #${tags[x].split('#')[1] || '888'} !important; color: #${isColorDark(tags[x].split('#')[1]) ? 'fff' : '000'} !important; 
    }
    .v-subscribe-button[data-subsite-id="${x}"] ~ ._tg .v-button__icon { 
      filter: ${isColorDark(tags[x].split('#')[1]) ? 'invert(1)' : 'none'}; 
    }`).join('\n');
}

function init(secondRun){  
  try {
    tags = JSON.parse(GM_getValue('tags', '{}') || '{}');
  } catch (e){
    tags = {};
  }
  if (!secondRun) addTagButton();
  tagsUpdate();
}

init(false);
GM_addValueChangeListener('tags', function(changes, namespace) {
  init(true);
});