MediaWiki:Modules/night-mode.js

Материал из Мракопедии
Перейти к: навигация, поиск

Замечание. Возможно, после сохранения вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl-F5 или Ctrl-R (⌘-R на Mac)
  • Google Chrome: Нажмите Ctrl-Shift-R (⌘-Shift-R на Mac)
  • Internet Explorer: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl-F5
  • Opera: Перейдите в Menu → Настройки (Opera → Настройки на Mac), а затем Безопасность → Очистить историю посещений → Кэшированные изображения и файлы
/********************************************************************************
* Этот модуль добавляет "ночной режим" и все, что с ним связано.
* 
* TODO:
* - найти способ обойти баг в Firefox с отрисовкой больших областей с фильтром, 
    который сейчас вызывает обрезание страницы на определенной высоте (вебкиты 
    работают нормально)
* - вынести это все в серверную тему
* - сделать механизм для инжектов в верстку, чтобы часть скриптов и стилей можно 
    было грузить в теле страницы. А то даже сраный {{#css:}} рисуется в теле 
    страницы без костылей, а я нет.
* - мотивировать Будкера на полноценный доступ к серверу, чтобы мне не приходилось 
    в дальнейшем издеваться над собой.
********************************************************************************/

~function() {

function setupNightMode() {
  if (!window.localStorage) {
    return;
  }

  $('<style>')
    .attr('id', 'night-mode-stylesheet')
    .html([
'body {',
'  background: black;',
'  filter: invert(100%) brightness(60%) saturate(10%);',
'  -moz-filter: invert(100%) brightness(60%) saturate(10%);',
'  -ms-filter: invert(100%) brightness(60%) saturate(10%);',
'  -o-filter: invert(100%) brightness(60%) saturate(10%);',
'  -webkit-filter: invert(100%) brightness(60%) saturate(10%);',
'}',
'*::selection {',
'  background-color: #888888;',
'}',
'*::-moz-selection {',
'  background-color: #888888;',
'}',
'*::-ms-selection {',
'  background-color: #888888;',
'}',
'*::-o-selection {',
'  background-color: #888888;',
'}',
'*::-webkit-selection {',
'  background-color: #888888;',
'}',
'img,#p-logo {',
'  filter: invert(100%);',
'  -moz-filter: invert(100%);',
'  -ms-filter: invert(100%);',
'  -o-filter: invert(100%);',
'  -webkit-filter: invert(100%);',
'  background-color: #ff9999;',
'  box-shadow: 0 0 10px 10px black inset;',
'  -moz-box-shadow: 0 0 10px 10px black inset;',
'  -ms-box-shadow: 0 0 10px 10px black inset;',
'  -o-box-shadow: 0 0 10px 10px black inset;',
'  -webkit-box-shadow: 0 0 10px 10px black inset;',
'}',
'a[href]:hover {',
'  text-shadow: 0 0 3px black, 0 0 10px black, 0 0 10px black;',
'  -moz-text-shadow: 0 0 3px black, 0 0 10px black, 0 0 10px black;',
'  -ms-text-shadow: 0 0 3px black, 0 0 10px black, 0 0 10px black;',
'  -o-text-shadow: 0 0 3px black, 0 0 10px black, 0 0 10px black;',
'  -webkit-text-shadow: 0 0 3px black, 0 0 10px black, 0 0 10px black;',
'  transition: 0.1s;',
'  -moz-transition: 0.1s;',
'  -ms-transition: 0.1s;',
'  -o-transition: 0.1s;',
'  -webkit-transition: 0.1s;',
'}',
'a[href] {',
'  transition: 2s;',
'  -moz-transition: 2s;',
'  -ms-transition: 2s;',
'  -o-transition: 2s;',
'  -webkit-transition: 2s;',
'}',
'#pt-night-mode {',
'  font-weight: bold;',
'}',
    ].join('\n'))
    .appendTo($('body'))
    .prop('disabled', true);
  
  $('<style>')
    .attr('id', 'uboa-stylesheet')
    .html([
'body {',
'  width: 100%;',
'  position: fixed;',
'}',
'#globalWrapper {',
'  animation: 0.001s linear 0s infinite alternate shaking;',
'  -moz-animation: 0.001s linear 0s infinite alternate shaking;',
'  -ms-animation: 0.001s linear 0s infinite alternate shaking;',
'  -o-animation: 0.001s linear 0s infinite alternate shaking;',
'  -webkit-animation: 0.001s linear 0s infinite alternate shaking;',
'  will-change: left;',
'  -moz-will-change: left;',
'  -ms-will-change: left;',
'  -o-will-change: left;',
'  -webkit-will-change: left;',
'}',
'* {',
'  pointer-events: none;',
'  -moz-pointer-events: none;',
'  -ms-pointer-events: none;',
'  -o-pointer-events: none;',
'  -webkit-pointer-events: none;',
'  cursor: default;',
'}',
'@keyframes shaking {',
'  from { left: -20px; }',
'  to { left: 20px; }',
'}',
'#uboa-static {',
'  background: url("https://mrakopedia.org/w/images/1/17/Static.gif") 0% 0% repeat;',
'  mix-blend-mode: multiply;',
'  -moz-mix-blend-mode: multiply;',
'  -ms-mix-blend-mode: multiply;',
'  -o-mix-blend-mode: multiply;',
'  -webkit-mix-blend-mode: multiply;',
'  width: 100vw;',
'  height: 100vh;',
'  filter: invert(100%);',
'  -moz-filter: invert(100%);',
'  -ms-filter: invert(100%);',
'  -o-filter: invert(100%);',
'  -webkit-filter: invert(100%);',
'  left: 0;',
'  top: 0;',
'  position: fixed;',
'}',
'#uboa {',
'  background: url("https://mrakopedia.org/w/images/1/1e/Uboa_huge.png") 50% 50%/contain no-repeat;',
'  width: 100vw;',
'  height: 100vh;',
'  filter: invert(100%);',
'  -moz-filter: invert(100%);',
'  -ms-filter: invert(100%);',
'  -o-filter: invert(100%);',
'  -webkit-filter: invert(100%);',
'  left: 0;',
'  top: 0;',
'  position: fixed;',
'}',
    
    ].join('\n'))
    .appendTo($('body'))
    .prop('disabled', true);

  var link;
  switch (mw.config.values.skin) {
    case 'monobook': {
      link = $('<a>')
        .text('ночной режим')
        .appendTo(
          $('<li>')
            .attr('id', 'pt-night-mode')
            .insertBefore($('#p-personal ul li:last'))
        )
      break;
    }
    case 'vector': {
      link = $('<a>')
        .text('Ночной режим')
        .appendTo(
          $('<li>')
            .attr('id', 'pt-night-mode')
            .insertBefore($('#p-personal ul li:last'))
        )
      break;
    }
    case 'modern': {
      link = $('<a>')
        .text('НОЧНОЙ РЕЖИМ')
        .appendTo(
          $('<li>')
            .attr('id', 'pt-night-mode')
            .insertBefore($('#p-personal ul li:last'))
        )
      break;
    }
  }
 
  if (link) {
    link
      .attr('title', 'Поменять цветовую схему на темную и красивую, чтобы ночью не жгло глазки (не играйтесь выключателем)')
      .attr('href', '#')
      .click(function() {
        toggleNightMode();
      });
  }
  
  updateNightMode();
}

function updateNightMode() {
  var enabled = localStorage.nightModeEnabled === "true";
  $('style#night-mode-stylesheet').prop('disabled', !enabled);
}

function toggleNightMode() {
  var enabled = localStorage.nightModeEnabled === "true";
  var firstEver = localStorage.nightModeEnabled == null;
  localStorage.nightModeEnabled = !enabled;
  
  updateNightMode();
  
  if (!enabled && !firstEver) {
    if (Math.random() * 64 < 1) {
      triggerUboa();
    }
  }
}

function triggerUboa() {
  var top = $('html').scrollTop();
  $('<div>')
    .attr('id', 'uboa-static')
    .css({ top: top + 'px' })
    .appendTo($('body'));
  $('<div>')
    .attr('id', 'uboa')
    .css({ top: top + 'px' })
    .appendTo($('body'));
  $('<audio>')
    .attr('src', 'https://mrakopedia.org/w/images/6/62/Uboa.mp3')
    .prop('autoplay', true)
    .prop('loop', true)
    .appendTo($('body'));
  $('body').css({ 'top': -top + 'px' });
  $('style#night-mode-stylesheet').prop('disabled', false);
  $('style#uboa-stylesheet').prop('disabled', false);
}

function finalizeNightMode() {
  setTimeout(function() {
    $('<style>')
      .attr('id', 'deferred-switch-stylesheet')
      .html([
'body {',
'  transition: 0.1s;',
'  -moz-filter: 0.1s;',
'  -ms-filter: 0.1s;',
'  -o-filter: 0.1s;',
'  -webkit-filter: 0.1s;',
'}',
      ].join('\n'))
      .appendTo($('body'));
  }, 100);
}

function enqueueSuddenUboa(prob) {
  setTimeout(function() {
    if (Math.random() < prob) {
      // да вы счастливчик! считайте, в лотерею выиграли.
      triggerUboa();
    } else {
      enqueueSuddenUboa();
    }
  }, 60000);
}

setupNightMode();

$(function() {
  finalizeNightMode();
  enqueueSuddenUboa(0.00001); // вероятность в минуту
  finishLoading('nightMode');
});

window.toggleNightMode = toggleNightMode;
window.triggerUboa = triggerUboa;

}();