init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1 @@
.hljs{display:block;overflow-x:auto;padding:0.5em;background:#F0F0F0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888888}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-selector-pseudo{color:#BC6060}.hljs-literal{color:#78A960}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,659 @@
var IV = {
notify: function(message) {
if (window.external && window.external.invoke) {
window.external.invoke(JSON.stringify(message));
}
},
frameClickHandler: function(e) {
var target = e.target;
var context = '';
while (target) {
if (target.id == 'menu_page_blocker') {
IV.notify({ event: 'menu_page_blocker_click' });
IV.menuShown(false);
return;
}
if (target.tagName == 'AUDIO' || target.tagName == 'VIDEO') {
return;
}
if (context === ''
&& target.hasAttribute
&& target.hasAttribute('data-context')) {
context = String(target.getAttribute('data-context'));
}
if (target.tagName == 'A') {
break;
}
target = target.parentNode;
}
if (!target || (context === '' && !target.hasAttribute('href'))) {
return;
}
var base = document.createElement('A');
base.href = window.location.href;
if (base.origin != target.origin
|| base.pathname != target.pathname
|| base.search != target.search) {
IV.notify({
event: 'link_click',
url: target.href,
context: context,
});
} else if (target.hash.length < 2) {
IV.jumpToHash('');
} else {
IV.jumpToHash(decodeURIComponent(target.hash.substr(1)));
}
e.preventDefault();
},
getElementTop: function (element) {
var top = 0;
while (element && !element.classList.contains('page-scroll')) {
top += element.offsetTop;
element = element.offsetParent;
}
return top;
},
jumpToHash: function (hash, instant) {
var current = IV.computeCurrentState();
current.hash = hash;
window.history.replaceState(
current,
'',
'page' + IV.index + '.html');
if (hash == '') {
IV.scrollTo(0, instant);
return;
}
var element = document.getElementsByName(hash)[0];
if (element) {
IV.scrollTo(IV.getElementTop(element), instant);
}
},
frameKeyDown: function (e) {
const key0 = (e.key === '0')
|| (e.code === 'Key0')
|| (e.keyCode === 48);
const keyW = (e.key === 'w')
|| (e.code === 'KeyW')
|| (e.keyCode === 87);
const keyQ = (e.key === 'q')
|| (e.code === 'KeyQ')
|| (e.keyCode === 81);
const keyM = (e.key === 'm')
|| (e.code === 'KeyM')
|| (e.keyCode === 77);
if ((e.metaKey || e.ctrlKey) && (keyW || keyQ || keyM || key0)) {
e.preventDefault();
IV.notify({
event: 'keydown',
modifier: e.ctrlKey ? 'ctrl' : 'cmd',
key: key0 ? '0' : keyW ? 'w' : keyQ ? 'q' : 'm',
});
} else if (e.key === 'Escape' || e.keyCode === 27) {
e.preventDefault();
if (IV.position) {
window.history.back();
} else {
IV.notify({
event: 'keydown',
key: 'escape',
});
}
}
},
frameMouseEnter: function (e) {
IV.notify({ event: 'mouseenter' });
},
frameMouseUp: function (e) {
IV.notify({ event: 'mouseup' });
},
lastScrollTop: 0,
frameScrolled: function (e) {
const was = IV.lastScrollTop;
IV.lastScrollTop = IV.findPageScroll().scrollTop;
IV.updateJumpToTop(was < IV.lastScrollTop);
IV.checkVideos();
},
updateJumpToTop: function (scrolledDown) {
if (IV.lastScrollTop < 100) {
document.getElementById('bottom_up').classList.add('hidden');
} else if (scrolledDown && IV.lastScrollTop > 200) {
document.getElementById('bottom_up').classList.remove('hidden');
}
},
updateStyles: function (styles) {
if (IV.styles !== styles) {
IV.styles = styles;
document.getElementsByTagName('html')[0].style = styles;
}
},
toggleChannelJoined: function (id, joined) {
IV.channelsJoined['channel' + id] = joined;
IV.checkChannelButtons();
},
checkChannelButtons: function() {
const channels = document.getElementsByClassName('channel');
for (var i = 0; i < channels.length; ++i) {
const channel = channels[i];
const full = String(channel.getAttribute('data-context'));
const value = IV.channelsJoined[full];
if (value !== undefined) {
channel.classList.toggle('joined', value);
}
}
},
slideshowSlide: function(el, delta) {
var dir = window.getComputedStyle(el, null).direction || 'ltr';
var marginProp = dir == 'rtl' ? 'marginRight' : 'marginLeft';
if (delta) {
var form = el.parentNode.firstChild;
var s = form.s;
const next = +s.value + delta;
s.value = (next == s.length) ? 0 : (next == -1) ? (s.length - 1) : next;
form.nextSibling.firstChild.style[marginProp] = (-100 * s.value) + '%';
} else {
el.form.nextSibling.firstChild.style[marginProp] = (-100 * el.value) + '%';
}
return false;
},
initPreBlocks: function() {
if (!hljs) {
return;
}
var pres = document.getElementsByTagName('pre');
for (var i = 0; i < pres.length; i++) {
if (pres[i].hasAttribute('data-language')) {
hljs.highlightBlock(pres[i]);
}
}
},
initEmbedBlocks: function() {
var iframes = document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; i++) {
(function(iframe) {
window.addEventListener('message', function(event) {
if (event.source !== iframe.contentWindow ||
event.origin != window.origin) {
return;
}
try {
var data = JSON.parse(event.data);
} catch(e) {
var data = {};
}
if (data.eventType == 'resize_frame') {
if (data.eventData.height) {
iframe.style.height = data.eventData.height + 'px';
}
}
}, false);
})(iframes[i]);
}
},
addRipple: function (button, x, y) {
const ripple = document.createElement('span');
ripple.classList.add('ripple');
const inner = document.createElement('span');
inner.classList.add('inner');
x -= button.offsetLeft;
y -= button.offsetTop;
const mx = button.clientWidth - x;
const my = button.clientHeight - y;
const sq1 = x * x + y * y;
const sq2 = mx * mx + y * y;
const sq3 = x * x + my * my;
const sq4 = mx * mx + my * my;
const radius = Math.sqrt(Math.max(sq1, sq2, sq3, sq4));
inner.style.width = inner.style.height = `${2 * radius}px`;
inner.style.left = `${x - radius}px`;
inner.style.top = `${y - radius}px`;
inner.classList.add('inner');
ripple.addEventListener('animationend', function (e) {
if (e.animationName === 'fadeOut') {
ripple.remove();
}
});
ripple.appendChild(inner);
button.appendChild(ripple);
},
stopRipples: function (button) {
const id = button.id ? button.id : button;
button = document.getElementById(id);
const ripples = button.getElementsByClassName('ripple');
for (var i = 0; i < ripples.length; ++i) {
const ripple = ripples[i];
if (!ripple.classList.contains('hiding')) {
ripple.classList.add('hiding');
}
}
},
init: function () {
var current = IV.computeCurrentState();
window.history.replaceState(current, '', IV.pageUrl(0));
IV.jumpToHash(current.hash, true);
IV.lastScrollTop = window.history.state.scroll;
IV.findPageScroll().onscroll = IV.frameScrolled;
const buttons = document.getElementsByClassName('fixed_button');
for (let i = 0; i < buttons.length; ++i) {
const button = buttons[i];
button.addEventListener('mousedown', function (e) {
IV.addRipple(e.currentTarget, e.clientX, e.clientY);
});
button.addEventListener('mouseup', function (e) {
const id = e.currentTarget.id;
setTimeout(function () {
IV.stopRipples(id);
}, 0);
});
button.addEventListener('mouseleave', function (e) {
IV.stopRipples(e.currentTarget);
});
}
IV.initMedia();
IV.notify({ event: 'ready' });
IV.forceScrollFocus();
IV.frameScrolled();
},
initMedia: function () {
var scroll = IV.findPageScroll();
const photos = scroll.getElementsByClassName('photo');
for (let i = 0; i < photos.length; ++i) {
const photo = photos[i];
if (photo.classList.contains('loaded')) {
continue;
}
const url = photo.style.backgroundImage;
if (!url || url.length < 7) {
continue;
}
var img = new Image();
img.onload = function () {
photo.classList.add('loaded');
}
img.src = url.substr(5, url.length - 7);
if (img.complete) {
photo.classList.add('loaded');
IV.stopAnimations(photo);
}
}
IV.videos = [];
const videos = scroll.getElementsByClassName('video');
for (let i = 0; i < videos.length; ++i) {
const element = videos[i];
IV.videos.push({
element: element,
src: String(element.getAttribute('data-src')),
autoplay: (element.getAttribute('data-autoplay') == '1'),
loop: (element.getAttribute('data-loop') == '1'),
small: (element.getAttribute('data-small') == '1'),
filled: (element.firstChild
&& element.firstChild.tagName == 'VIDEO'),
});
}
},
checkVideos: function () {
const visibleTop = IV.lastScrollTop;
const visibleBottom = visibleTop + IV.findPageScroll().offsetHeight;
const videos = IV.videos;
for (let i = 0; i < videos.length; ++i) {
const video = videos[i];
const element = video.element;
const wrap = element.offsetParent; // video-wrap
const top = IV.getElementTop(wrap);
const bottom = top + wrap.offsetHeight;
if (top < visibleBottom && bottom > visibleTop) {
if (!video.created) {
video.created = new Date();
video.loaded = false;
element.innerHTML = '<video muted class="'
+ (video.small ? 'video-small' : '')
+ '"'
+ (video.autoplay
? ' preload="auto" autoplay'
: (video.small
? ''
: ' controls'))
+ (video.loop ? ' loop' : '')
+ ' oncanplay="IV.checkVideos();"'
+ ' onloadeddata="IV.checkVideos();">'
+ '<source src="'
+ video.src
+ '" type="video/mp4" />'
+ '</video>';
var media = element.firstChild;
media.oncontextmenu = function () { return false; };
media.oncanplay = IV.checkVideos;
media.onloadeddata = IV.checkVideos;
}
} else if (video.created && video.autoplay) {
video.created = false;
element.innerHTML = '';
}
if (video.created && !video.loaded) {
var media = element.firstChild;
const HAVE_CURRENT_DATA = 2;
if (media && media.readyState >= HAVE_CURRENT_DATA) {
video.loaded = true;
media.classList.add('loaded');
if ((new Date() - video.created) < 100) {
IV.stopAnimations(media);
}
}
}
}
},
showTooltip: function (text) {
var toast = document.createElement('div');
toast.classList.add('toast');
toast.textContent = text;
document.body.appendChild(toast);
setTimeout(function () {
toast.classList.add('hiding');
}, 2000);
setTimeout(function () {
document.body.removeChild(toast);
}, 3000);
},
scrollTo: function (y, instant) {
if (y < 200) {
document.getElementById('bottom_up').classList.add('hidden');
}
IV.findPageScroll().scrollTo({
top: y || 0,
behavior: instant ? 'instant' : 'smooth'
});
},
computeCurrentState: function () {
var now = IV.findPageScroll();
return {
position: IV.position,
index: IV.index,
hash: ((!window.history.state
|| window.history.state.hash === undefined)
? window.location.hash.substr(1)
: window.history.state.hash),
scroll: now ? now.scrollTop : 0
};
},
pageUrl: function (index, hash) {
var result = 'page' + index + '.html';
if (hash) {
result += '#' + hash;
}
return result;
},
navigateTo: function (index, hash) {
if (!index && !IV.index) {
IV.navigateToDOM(IV.index, hash);
return;
}
IV.pending = [index, hash];
if (!IV.cache[index]) {
IV.loadPage(index);
} else if (IV.cache[index].dom) {
IV.navigateToDOM(index, hash);
} else if (IV.cache[index].content) {
IV.navigateToLoaded(index, hash);
}
},
applyUpdatedContent: function (index) {
if (IV.index != index) {
IV.cache[index].contentUpdated = (IV.cache[index].dom !== undefined);
return;
}
var data = JSON.parse(IV.cache[index].content);
var article = function (el) {
return el.getElementsByTagName('article')[0];
};
var footer = function (el) {
return el.getElementsByClassName('page-footer')[0];
};
var from = IV.findPageScroll();
var to = IV.makeScrolledContent(data.html);
morphdom(article(from), article(to), {
onBeforeElUpdated: function (fromEl, toEl) {
if (fromEl.classList.contains('video')
&& toEl.classList.contains('video')
&& fromEl.hasAttribute('data-src')
&& toEl.hasAttribute('data-src')
&& (fromEl.getAttribute('data-src')
== toEl.getAttribute('data-src'))) {
return false;
} else if (fromEl.tagName == 'SECTION'
&& fromEl.classList.contains('channel')
&& fromEl.hasAttribute('data-context')
&& toEl.tagName == 'SECTION'
&& toEl.classList.contains('channel')
&& toEl.hasAttribute('data-context')
&& (String(fromEl.getAttribute('data-context'))
== String(toEl.getAttribute('data-context')))) {
return false;
} else if (fromEl.classList.contains('loaded')) {
toEl.classList.add('loaded');
}
return !fromEl.isEqualNode(toEl);
}
});
morphdom(footer(from), footer(to));
IV.initMedia();
eval(data.js);
},
loadPage: function (index) {
if (!IV.cache[index]) {
IV.cache[index] = {};
}
IV.cache[index].loading = true;
let xhr = new XMLHttpRequest();
xhr.onload = function () {
IV.cache[index].loading = false;
IV.cache[index].content = xhr.responseText;
IV.applyUpdatedContent(index);
if (IV.pending && IV.pending[0] == index) {
IV.navigateToLoaded(index, IV.pending[1]);
}
if (IV.cache[index].reloadPending) {
IV.cache[index].reloadPending = false;
IV.reloadPage(index);
}
}
xhr.open('GET', 'page' + index + '.json');
xhr.send();
},
reloadPage: function (index) {
if (IV.cache[index] && IV.cache[index].loading) {
IV.cache[index].reloadPending = true;
return;
}
IV.loadPage(index);
},
makeScrolledContent: function (html) {
var result = document.createElement('div');
result.className = 'page-scroll';
result.tabIndex = '-1';
result.innerHTML = html.trim();
result.onscroll = IV.frameScrolled;
return result;
},
navigateToLoaded: function (index, hash) {
if (IV.cache[index].dom) {
IV.navigateToDOM(index, hash);
} else {
var data = JSON.parse(IV.cache[index].content);
IV.cache[index].dom = IV.makeScrolledContent(data.html);
IV.navigateToDOM(index, hash);
eval(data.js);
}
},
navigateToDOM: function (index, hash) {
IV.pending = null;
if (IV.index == index) {
IV.jumpToHash(hash);
IV.forceScrollFocus();
return;
}
window.history.replaceState(
IV.computeCurrentState(),
'',
IV.pageUrl(IV.index));
IV.position = IV.position + 1;
window.history.pushState(
{ position: IV.position, index: index, hash: hash },
'',
IV.pageUrl(index));
IV.showDOM(index, hash);
},
findPageScroll: function () {
var all = document.getElementsByClassName('page-scroll');
for (i = 0; i < all.length; ++i) {
if (!all[i].classList.contains('hidden-left')
&& !all[i].classList.contains('hidden-right')) {
return all[i];
}
}
return null;
},
showDOM: function (index, hash, scroll) {
IV.pending = null;
if (IV.index != index) {
var initial = !window.history.state
|| window.history.state.position === undefined;
var back = initial
|| IV.position > window.history.state.position;
IV.position = initial ? 0 : window.history.state.position;
var now = IV.cache[index].dom;
var was = IV.findPageScroll();
if (!IV.cache[IV.index]) {
IV.cache[IV.index] = {};
}
IV.cache[IV.index].dom = was;
was.parentNode.appendChild(now);
if (scroll !== undefined) {
now.scrollTop = scroll;
setTimeout(function () {
// When returning by history.back to an URL with a hash
// for the first time browser forces the scroll to the
// hash instead of the saved scroll position.
//
// This workaround prevents incorrect scroll position.
now.scrollTop = scroll;
}, 0);
}
now.classList.add(back ? 'hidden-left' : 'hidden-right');
now.classList.remove(back ? 'hidden-right' : 'hidden-left');
IV.stopAnimations(now.firstChild);
if (!was.listening) {
was.listening = true;
was.firstChild.addEventListener('transitionend', function (e) {
if (was.classList.contains('hidden-left')
|| was.classList.contains('hidden-right')) {
if (was.parentNode) {
was.parentNode.removeChild(was);
var videos = was.getElementsByClassName('video');
for (var i = 0; i < videos.length; ++i) {
videos[i].innerHTML = '';
}
}
}
});
}
was.classList.add(back ? 'hidden-right' : 'hidden-left');
now.classList.remove(back ? 'hidden-left' : 'hidden-right');
IV.index = index;
IV.notify({
event: 'location_change',
index: IV.index,
position: IV.position,
hash: IV.computeCurrentState().hash,
});
if (IV.cache[index].contentUpdated) {
IV.cache[index].contentUpdated = false;
IV.applyUpdatedContent(index);
} else {
IV.initMedia();
}
IV.checkChannelButtons();
if (scroll === undefined) {
IV.jumpToHash(hash, true);
} else {
IV.lastScrollTop = scroll;
IV.updateJumpToTop(true);
}
} else if (scroll !== undefined) {
IV.scrollTo(scroll);
IV.lastScrollTop = scroll;
IV.updateJumpToTop(true);
} else {
IV.jumpToHash(hash);
}
IV.forceScrollFocus();
IV.frameScrolled();
},
forceScrollFocus: function () {
IV.findPageScroll().focus();
setTimeout(function () {
// Doesn't work on #hash-ed pages in Windows WebView2 otherwise.
IV.findPageScroll().focus();
}, 100);
},
stopAnimations: function (element) {
element.getAnimations().forEach(
(animation) => animation.finish());
},
menuShown: function (shown) {
var already = document.getElementById('menu_page_blocker');
if (already && shown) {
return;
} else if (already) {
document.body.removeChild(already);
return;
} else if (!shown) {
return;
}
var blocker = document.createElement('div');
blocker.id = 'menu_page_blocker';
document.body.appendChild(blocker);
},
videos: {},
videosPlaying: {},
cache: {},
channelsJoined: {},
index: 0,
position: 0
};
document.onclick = IV.frameClickHandler;
document.onkeydown = IV.frameKeyDown;
document.onmouseenter = IV.frameMouseEnter;
document.onmouseup = IV.frameMouseUp;
document.onresize = IV.checkVideos;
window.onmessage = IV.postMessageHandler;
window.addEventListener('popstate', function (e) {
if (e.state) {
IV.showDOM(e.state.index, e.state.hash, e.state.scroll);
}
});
document.addEventListener("DOMContentLoaded", IV.forceScrollFocus);