295 lines
11 KiB
JavaScript
295 lines
11 KiB
JavaScript
// ==UserScript==
|
|
// @name kimarp aKKKoma modifications
|
|
// @version 1
|
|
// @grant none
|
|
// @inject-into page
|
|
// ==/UserScript==
|
|
|
|
// ViolentMonkey Recommended For This Script
|
|
|
|
;(_=>{
|
|
if (!((document.querySelector("noscript")??{}).innerText == "To use Akkoma, please enable JavaScript.")) {
|
|
return;
|
|
}
|
|
|
|
console.log("activating evil akkoma mode");
|
|
let nonce = document.querySelector("script").nonce;
|
|
|
|
// getEventListeners(elem: EventTarget, event; string): Set
|
|
//
|
|
// Get event listeners of an EventTarget.
|
|
// Return value: Set object containing the event listeners in question.
|
|
//
|
|
// Modifications of the returned Set by the caller results in undefined behavior.
|
|
//
|
|
let getEventListeners = ((proto, addEventListener, removeEventListener, elems, ensure, ensurex) => (
|
|
// murder
|
|
addEventListener = proto.addEventListener,
|
|
removeEventListener = proto.removeEventListener,
|
|
elems = new WeakMap(),
|
|
ensure = k => (elems.get(k) ?? ensure((elems.set(k, new Map()), k))),
|
|
ensurex = (els, k) => (els.get(k) ?? (els.set(k, new Set()), ensurex(els, k))),
|
|
proto.addEventListener = function(t, lis, ...rest) {
|
|
let ret = addEventListener.apply(this, [t, lis, ...rest]);
|
|
ensurex(ensure(this), t).add(lis);
|
|
return ret;
|
|
},
|
|
proto.removeEventListener = function(t, lis, ...rest) {
|
|
let ret = addEventListener.apply(this, [t, lis, ...rest]);
|
|
ensurex(ensure(this), t).delete(lis);
|
|
return ret;
|
|
},
|
|
function(elem, t) {
|
|
return ensurex(ensure(elem), t);
|
|
}
|
|
))(unsafeWindow.EventTarget.prototype);
|
|
|
|
let style = document.createElement("style");
|
|
style.nonce = nonce;
|
|
style.textContent=`
|
|
._mfm_x2_ ._mfm_x2_ ._mfm_x2_,
|
|
._mfm_x2_ ._mfm_x2_ ._mfm_x3_,
|
|
._mfm_x2_ ._mfm_x2_ ._mfm_x4_,
|
|
._mfm_x2_ ._mfm_x3_ ._mfm_x2_,
|
|
._mfm_x2_ ._mfm_x3_ ._mfm_x3_,
|
|
._mfm_x2_ ._mfm_x3_ ._mfm_x4_,
|
|
._mfm_x2_ ._mfm_x4_ ._mfm_x2_,
|
|
._mfm_x2_ ._mfm_x4_ ._mfm_x3_,
|
|
._mfm_x2_ ._mfm_x4_ ._mfm_x4_,
|
|
._mfm_x3_ ._mfm_x2_ ._mfm_x2_,
|
|
._mfm_x3_ ._mfm_x2_ ._mfm_x3_,
|
|
._mfm_x3_ ._mfm_x2_ ._mfm_x4_,
|
|
._mfm_x3_ ._mfm_x3_ ._mfm_x2_,
|
|
._mfm_x3_ ._mfm_x3_ ._mfm_x3_,
|
|
._mfm_x3_ ._mfm_x3_ ._mfm_x4_,
|
|
._mfm_x3_ ._mfm_x4_ ._mfm_x2_,
|
|
._mfm_x3_ ._mfm_x4_ ._mfm_x3_,
|
|
._mfm_x3_ ._mfm_x4_ ._mfm_x4_,
|
|
._mfm_x4_ ._mfm_x2_ ._mfm_x2_,
|
|
._mfm_x4_ ._mfm_x2_ ._mfm_x3_,
|
|
._mfm_x4_ ._mfm_x2_ ._mfm_x4_,
|
|
._mfm_x4_ ._mfm_x3_ ._mfm_x2_,
|
|
._mfm_x4_ ._mfm_x3_ ._mfm_x3_,
|
|
._mfm_x4_ ._mfm_x3_ ._mfm_x4_,
|
|
._mfm_x4_ ._mfm_x4_ ._mfm_x2_,
|
|
._mfm_x4_ ._mfm_x4_ ._mfm_x3_,
|
|
._mfm_x4_ ._mfm_x4_ ._mfm_x4_ {
|
|
font-size:100%;
|
|
}
|
|
|
|
.user-profile .user-profile-fields .user-profile-field .user-profile-field-name, .user-profile .user-profile-fields .user-profile-field .user-profile-field-value {
|
|
white-space: unset;
|
|
}
|
|
|
|
body.EvilMode-EvilCode pre:has(code),
|
|
body.EvilMode-EvilCode :not(pre) > code {
|
|
background-color: #000;
|
|
color: #fff;
|
|
padding:0.3em;
|
|
/* border:1px solid #0000ff; */
|
|
font-size:0.8em;
|
|
}
|
|
|
|
body.EvilMode-EvilCode pre:has(code) {
|
|
box-shadow: 0 0 2em 0 #300;
|
|
}
|
|
|
|
body:not(.EvilMode-WrapCode) .StatusBody .text > pre {
|
|
white-space: pre;
|
|
}
|
|
|
|
:is(pre:has(code), :not(pre) > code) a {
|
|
color: #0f0;
|
|
}
|
|
|
|
body {
|
|
font-size:1.1em;
|
|
}
|
|
|
|
.Status .status-container .content, .StatusBody {
|
|
overflow: visible;
|
|
}
|
|
|
|
`
|
|
document.head.append(style);
|
|
|
|
document.addEventListener("DOMContentLoaded",_=>{
|
|
try {
|
|
[...document.styleSheets]
|
|
.map(e=>{try{return e.cssRules}catch{}}).filter(e=>e).map(e=>[...e])
|
|
.flat()
|
|
.filter(e=>e.selectorText==".user-info.-compact .container")
|
|
[0].style.gridTemplateAreas="";
|
|
} catch {}
|
|
|
|
var elemx = function(tag,ns,a,b) {
|
|
tag = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
Object.entries(a??{}).forEach(([k,v]) => tag.setAttribute(k,v));
|
|
(b??[]).map(e => (typeof e) == "string" ? document.createTextNode(e) : e)
|
|
.forEach(e => tag.append(e));
|
|
return tag;
|
|
};
|
|
|
|
var elem = function(tag,a,b){
|
|
return elemx(tag,null,a,b);
|
|
};
|
|
|
|
var $ = (query, base) => base ? base.querySelectorAll(query) : document.querySelectorAll(query);
|
|
var $0 = (query, base) => base ? base.querySelector(query) : document.querySelector(query);
|
|
|
|
var lastComment;
|
|
|
|
var eatComments = x => (x
|
|
.flatMap(e => [...e.removedNodes])
|
|
.filter(e => e instanceof Comment)
|
|
.forEach(e => lastComment = {obj: e, prev: e.prevSibling})
|
|
,x);
|
|
|
|
var findAllShowHide = e => ({
|
|
unhiders: [...$(".text-wrapper:not(.-tall-status) > .cw-status-hider", e)].filter(e => e.checkVisibility()),
|
|
hiders: [...$(".text-wrapper:not(.-tall-status) > .status-unhider", e)].filter(e => e.checkVisibility()),
|
|
})
|
|
|
|
var aquireParentThread = e => {
|
|
while (e) {
|
|
if (e.matches(".thread-body")) return e;
|
|
e = e.parentElement;
|
|
}
|
|
};
|
|
|
|
new MutationObserver(x => eatComments(x)
|
|
.flatMap(e => [...e.addedNodes])
|
|
.filter(e => e.matches && e.matches('.Conversation .ExtraButtons div.popover'))
|
|
.map(e => $0("div.dropdown-menu", e))
|
|
.forEach((e, x, exp, thread) => e.prepend((
|
|
thread = aquireParentThread(e),
|
|
console.log("MEOW", thread, findAllShowHide(thread)),
|
|
x = elem("button", {class: "button-default dropdown-item dropdown-item-icon"}, [
|
|
elemx("svg", "http://www.w3.org/2000/svg", {
|
|
class: "svg-inline--fa fa-fw",
|
|
"aria-hidden": "true",
|
|
focusable: "false",
|
|
"data-prefix": "fas",
|
|
"data-icon": "",
|
|
role: "img",
|
|
viewBox: "0 0 100 100",
|
|
}, [
|
|
elemx("path", "http://www.w3.org/2000/svg", {
|
|
class: "",
|
|
fill: "currentColor",
|
|
d: "m 50.660539,0.0045101 c -0.645534,-0.01213881 -1.294703,1.754e-5 -1.945858,0.03899735 -1.411948,0.0845229 -2.835684,0.31198703 -4.257516,0.64938883 C 38.542997,1.8005311 33.899147,5.1598476 30.643098,8.9077496 27.383379,12.659877 25.219091,16.79805 23.376192,20.411935 L 3.7381004,57.047298 3.9142268,56.738711 C -7.5703242,75.610959 7.7541966,101.94204 29.914884,99.886616 h 42.92403 l -0.116853,-0.0017 C 83.788836,100.08403 92.592574,92.975791 96.831053,84.247017 101.0024,75.656523 101.41478,64.907121 95.896233,56.118138 L 73.683982,14.684427 C 69.268882,6.0241919 60.343554,0.18659192 50.660539,0.0045101 Z M 49.434428,13.082149 c 0.708497,-0.02575 1.4264,0.01697 2.142307,0.122078 4.295437,0.630654 8.539948,3.513478 10.521857,7.400998 a 6.5037781,6.5114945 0 0 0 0.06266,0.118688 l 22.308777,41.61514 a 6.5037781,6.5114945 0 0 0 0.291286,0.490009 c 2.873436,4.390121 2.843963,10.634761 0.372575,15.724365 -2.47139,5.089603 -6.686363,8.412003 -12.178123,8.313195 a 6.5037781,6.5114945 0 0 0 -0.116857,-0.0017 H 29.745531 a 6.5037781,6.5114945 0 0 0 -0.736682,0.04236 C 17.71564,88.197456 9.1296536,73.196865 15.022043,63.514057 A 6.5037781,6.5114945 0 0 0 15.19817,63.20547 L 34.839648,26.565021 a 6.5037781,6.5114945 0 0 0 0.06266,-0.118687 c 1.767303,-3.467518 3.585064,-6.727822 5.553062,-8.993102 1.967993,-2.265282 3.79268,-3.517979 6.467563,-3.992979 a 6.5037781,6.5114945 0 0 0 0.423377,-0.08986 c 0.68052,-0.168284 1.379616,-0.262494 2.088114,-0.288241 z m 0.613056,5.413835 c -1.393903,0 -2.595462,0.565514 -3.603817,1.693836 -0.978698,1.128323 -1.466591,2.627607 -1.466591,4.498247 0,0.77201 0.08794,1.944516 0.265883,3.51823 l 3.915425,36.077531 h 1.690136 l 4.003488,-36.077531 c 0.11863,-1.276786 0.177819,-2.271513 0.177819,-2.984137 0,-2.226952 -0.489585,-3.904017 -1.468284,-5.03234 -0.94904,-1.128322 -2.120157,-1.693836 -3.514059,-1.693836 z m -0.08806,53.180365 c -1.364245,0 -2.537055,0.490167 -3.515753,1.470026 -0.94904,0.950166 -1.422559,2.09389 -1.422559,3.430062 0,1.365863 0.473519,2.53837 1.422559,3.518229 0.978698,0.950165 2.151508,1.424247 3.515753,1.424247 1.364246,0 2.520989,-0.474082 3.470028,-1.424247 0.978699,-0.979859 1.466592,-2.152366 1.466591,-3.518229 0,-1.336172 -0.487892,-2.479896 -1.466591,-3.430062 -0.949039,-0.979859 -2.105782,-1.470026 -3.470028,-1.470026 z"
|
|
})
|
|
]),
|
|
elem("span", {}, [((exp = findAllShowHide(thread).unhiders.length != 0) ? "Expand" : "Close") + " all CWs"])
|
|
]),
|
|
x.addEventListener("click", ev => (
|
|
ev = findAllShowHide(thread),
|
|
(exp ? ev.unhiders : ev.hiders).forEach(e => e.click()),
|
|
[...e.children]
|
|
.flatMap(e => [...getEventListeners(e,'click')])
|
|
.filter(e => e?.value)
|
|
.filter(e => e.value[1])
|
|
.filter(e=>e.value[1].name=="bound hidePopover")
|
|
.map(e => e.value[1])[0]()
|
|
)), x
|
|
)))
|
|
)
|
|
.observe(document.body, {childList:true, subtree:true})
|
|
|
|
let makeCheckBox = (label, params, eater) => {
|
|
let checkb;
|
|
|
|
let textel = elem("li", {}, [
|
|
elem("label", {class: "BooleanSetting"}, [
|
|
elem("label", {class: "checkbox"}, [
|
|
checkb = elem("input", {type: "checkbox", ...params}),
|
|
elem("i", {class: "checkbox-indicator"}),
|
|
elem("span", {class: "label"}, [
|
|
elem("span", {class: "label"}, [
|
|
label
|
|
])
|
|
])
|
|
])
|
|
])
|
|
]);
|
|
|
|
if (eater)
|
|
eater(checkb);
|
|
|
|
return textel;
|
|
}
|
|
|
|
let makeNumberal = (label, params, eater) => {
|
|
let checkb;
|
|
|
|
let textel = elem("li", {}, [
|
|
elem("span", {class: "IntegerSetting"}, [
|
|
elem("label", {for: params.id, style: "margin-right: 1em"}, [label]),
|
|
checkb = elem("input", {class: "number-input", type: "number", ...params})
|
|
])
|
|
]);
|
|
|
|
if (eater)
|
|
eater(checkb);
|
|
|
|
return textel;
|
|
}
|
|
|
|
var settings;
|
|
var save = _ => localStorage.aKKKomaSettings = JSON.stringify(settings);
|
|
var load = _ => settings = JSON.parse(localStorage.aKKKomaSettings ?? '{}')
|
|
|
|
try {
|
|
load(); save();
|
|
} catch {
|
|
delete localStorage.aKKKomaSettings;
|
|
load(); save();
|
|
}
|
|
|
|
var inputValuator = inp => (inp.getAttribute("type") == "checkbox" ? {
|
|
set: (v) => (inp.checked = !!v),
|
|
get: () => inp.checked,
|
|
event: "change"
|
|
} : {
|
|
set: (v) => (inp.value = v),
|
|
get: () => inp.value,
|
|
event: "input"
|
|
}
|
|
);
|
|
|
|
var inputValueObserver = (id, f) => inp => void (
|
|
settings[id] != null && (inputValuator(inp).set(settings[id])),
|
|
f = (f => ev => ((settings[id] = inputValuator(inp).get()), save(),
|
|
console.log(`${id}: ${settings[id]}`),
|
|
f ? f(settings[id], inp, ev) : [][[]]))(f),
|
|
inp.addEventListener(inputValuator(inp).event, f), f()
|
|
);
|
|
|
|
var setelem = elem("div", {class: "setting-item"}, [
|
|
elem("h2", {}, ["Evil Mode"]),
|
|
elem("ul", {class: "setting-list"}, [
|
|
|
|
makeNumberal("Font size", {id: "EvilMode-FontSize", value: 1, step: 0.1},
|
|
inputValueObserver("fontSize", val => document.body.style.fontSize = val + "em")),
|
|
|
|
makeCheckBox("EVIL code blocks", {id: "EvilMode-EvilCode"},
|
|
inputValueObserver("evilCodeBlocks", val => val
|
|
? document.body.classList.add("EvilMode-EvilCode")
|
|
: document.body.classList.remove("EvilMode-EvilCode"))),
|
|
|
|
makeCheckBox("Wrap code blocks", {id: "EvilMode-WrapCode", checked: ""},
|
|
inputValueObserver("wrapCodeBlocks", val => val
|
|
? document.body.classList.add("EvilMode-WrapCode")
|
|
: document.body.classList.remove("EvilMode-WrapCode")))
|
|
])
|
|
]);
|
|
|
|
var smp_i = setInterval(_ => {
|
|
var x = document.querySelector(".settings-modal-panel > .panel-body > * > .contents > div > div > div > div");
|
|
if (!x) return;
|
|
clearInterval(smp_i);
|
|
x.insertAdjacentElement("afterEnd", setelem);
|
|
}, 50);
|
|
});
|
|
})();
|