您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fix "new" reddit behaviour: long-lived page, internal links, moderator page
// ==UserScript== // @name Reddit - fix "new" // @namespace https://github.com/Procyon-b // @version 0.6.11 // @description Fix "new" reddit behaviour: long-lived page, internal links, moderator page // @author Achernar // @match https://*.reddit.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @run-at document-start // ==/UserScript== (function() { "use strict"; //à if (document.contentType != 'text/html') return; var react, tit={}, options={}, updated={}; const version='0.6.11'; const defOpts={ version: '', enable_LLP: false, enable_LLPv2_2: false, enable_LLPv3_2: false, enable_LLPv4: true, timed_LLP: false, LLP_TO: 1000, hide_NP: false, no_tit: false, loadMsg: false, misc_disLLPstatus: true, lnk_rw_intf: true, lnk_rw_cmt_www: true, lnk_rw_cmt_old: false, lnk_rw_chat: true, stay_new: true, stay_new_old: false, force_new: false, mod_modLog_r: true, mod_modLog_hide: false, mod_queues_r: true, mod_queues_hide: false, mod_LnF_r: true, mod_LnF_hide: false, mod_Rules_r: true, mod_Rules_hide: false, mod_RmvR_r: true, mod_RmvR_hide: false, mod_UMng_r: true, mod_UMng_hide: false, mod_UMng2_hide: false, mod_fix_modmail: true, lnk_ext_noref: true, lnk_rm_utm: true, misc_mark: false, misc_rst_o: false, misc_nolabel: false, misc_noblur: false, }, dlgT=[ ['-', '<span new>New options have been added.</span><a new id="dismiss">Dismiss</a>'], ['{','"Long-lived" page:'], ['enable_LLP', 'Trigger long-lived page (enable only if needed)', 'checkbox'], ['-'], ['{'], ['enable_LLPv4', 'Use "clever" method (experimental)', 'checkbox', ['data-grp=enable_LLPv', 'new_0_5'] ], ['enable_LLPv3_2', 'Use "forced" method', 'checkbox', ['data-grp=enable_LLPv', 'new_0_4_4'] ], ['enable_LLPv2_2', 'Use redirect method (last resort)', 'checkbox', ['data-grp=enable_LLPv', 'new_0_4_2'] ], ['-'], ['timed_LLP', 'Delay "new post" closing', 'checkbox'], ['LLP_TO', '"new post" display time (ms)', 'text', ['style="width: 4em;"', 'onchange="this.value=/^\\D*(\\d+).*$/.exec(this.value)[1]"'] ], ['}'], ['-'], ['hide_NP', 'Hide "new post" form during the trick (empty screen)', 'checkbox'], ['no_tit', 'Don\'t try to fix incorrect page title', 'checkbox'], ['loadMsg', 'Show loading sign', 'checkbox', ['new_0_5']], ['misc_disLLPstatus', 'Display LLP status in menu', 'checkbox', ['new_0_5']], ['}'], ['-'], ['{', 'Rewrite links:'], ['', 'Notifications links are already rewritten to "new." by default. You can change the behavior of other links.'], ['-'], ['lnk_rw_intf', 'Rewrite interface links', 'checkbox'], ['lnk_rw_cmt_www', 'Rewrite "www." links in posts & comments', 'checkbox'], ['lnk_rw_cmt_old', 'Rewrite "old." links in posts & comments', 'checkbox'], ['lnk_rw_chat', 'Rewrite in "Chat" too', 'checkbox', ['new_0_4_0']], ['-'], ['stay_new', 'Try to keep navigating on "new."', 'checkbox'], ['stay_new_old', '... on "new." also from "old." all comments', 'checkbox', ['new_0_4_0']], ['force_new', 'Force-redirect all access on "www." to "new."', 'checkbox'], ['}'], ['-'], ['{','Moderation page:'], ['mod_modLog_r', 'Add menu item to old "Mod Log" page', 'checkbox'], ['mod_modLog_hide', 'Hide current "Mod Log" menu item', 'checkbox'], ['-'], ['mod_queues_r', 'Add menu item to old "Queues" page', 'checkbox', ['new_0_6_2']], ['mod_queues_hide', 'Hide current "Queues" menu item', 'checkbox', ['new_0_6_2']], ['-'], ['mod_LnF_r', 'Add back removed old menu items from "Look & feel" (community styling, post & user flair)', 'checkbox', ['new_0_6_4']], ['mod_LnF_hide', 'Hide current "Look & feel" menu item', 'checkbox', ['new_0_6_4']], ['-'], ['mod_Rules_r', 'Add menu item to old "Rules" page', 'checkbox', ['new_0_6_6']], ['mod_Rules_hide', 'Hide current "Rules" menu item', 'checkbox', ['new_0_6_6']], ['-'], ['mod_RmvR_r', 'Add menu item to old "Removal reasons" page', 'checkbox', ['new_0_6_8']], ['mod_RmvR_hide', 'Hide current "Saved Responses" menu item', 'checkbox', ['new_0_6_8']], ['-'], ['mod_UMng_r', 'Add menu item to old "User Management" page', 'checkbox', ['new_0_6_9']], ['mod_UMng_hide', 'Hide current "Restrited users" menu item', 'checkbox', ['new_0_6_9']], ['mod_UMng2_hide', 'Hide current "Mods and members" menu item', 'checkbox', ['new_0_6_11']], ['-'], ['mod_fix_modmail', 'Fix links also in Modmail', 'checkbox'], ['}'], ['-'], ['{','Misc:'], ['lnk_ext_noref', 'Add <code>rel="noreferrer"</code> to external links', 'checkbox'], ['lnk_rm_utm', 'Remove tracking <code>&utm_</code> parameter from all links', 'checkbox', ['new_0_5']], ['}'], ['-'], ['{','This dialog:'], ['misc_mark', 'Mark option difference from current and default value', 'checkbox'], ['misc_rst_o', 'Clicking on the diff mark resets the value', 'checkbox'], ['misc_nolabel', 'Clicking on text label of options doesn\'t toggle option', 'checkbox'], ['misc_noblur', 'Don\'t blur background', 'checkbox', ['new_0_4_6']], ['}'], ['-'], ['{','Infos:'], ['', '<a href="https://procyon-b.github.io/programming/" target="_blank" rel="noreferrer noopener">Homepage</a> – <a href="https://greasyfork.org/scripts/493986" target="_blank" rel="noreferrer noopener">Script page</a><version>v'+version+'</version>'], ['}'], ]; function getOpts() { try{ options=GM_getValue('options'); options=Object.assign({}, defOpts, options); }catch(e){ Object.assign(options, defOpts); } try{ updated=GM_getValue('updated', {}); }catch(e){} } function saveOpts(opt = options) { var o, k; for (k in opt) { if ( (defOpts[k] != undefined) && (opt[k] != defOpts[k]) ) { if (!o) o={}; o[k]=opt[k]; } } if (o) GM_setValue('options', o); else GM_deleteValue('options'); if (Object.keys(updated).length) GM_setValue('updated', updated); else GM_deleteValue('updated'); } getOpts(); if (!options.version) { options.version=version; saveOpts(); } if (options.version != version) { // special fix if (version == '0.5') { // reddit has enabled LLP everywhere options.enable_LLP=false; } updated['new_'+version.replace(/\./g,'_')]=0; options.version=version; saveOpts(); } const showNew = 1209600000; if (Object.keys(updated).length) { let k, now=Date.now(); for (k in updated) { if ( updated[k] && ((updated[k] + showNew) < now) ) delete updated[k]; } saveOpts(); } var st=document.createElement('style'); function ins() { document.removeEventListener('DOMContentLoaded', ins); window.removeEventListener('load', ins); document.documentElement.appendChild(st); document.body.addEventListener('click', function(ev){ if (ev.target.classList.contains('icon-views')) { setOptions(); } }); } if (document.readyState != 'loading') ins(); else { document.addEventListener('DOMContentLoaded', ins); window.addEventListener('load', ins); } function tryUntil(F, TO=150, c=-1, fail) { if (!c--) { fail && fail(); return; } try{F();}catch(e){setTimeout(function(){tryUntil(F,TO,c,fail);}, TO)} } tryUntil( function(){document.documentElement.appendChild(st);} ); st.textContent=`.icon-views {cursor: pointer;} .hideEdit ~ div { position: fixed; top: 0; opacity: 0; z-index: -1; } body.trick #SHORTCUT_FOCUSABLE_DIV > div:has( #AppRouter-main-content .ListingLayout-outerContainer > ._3ozFtOe6WpJEMUtxDOIvtU > div:first-child:empty + div[style] + div[style*="px"]) ~ div > ._1DK52RbaamLOWw5UPaht_S, body.trick #AppRouter-main-content .ListingLayout-outerContainer > ._3ozFtOe6WpJEMUtxDOIvtU > div:first-child:empty + div[style] + div[style*="px"] {display: none;} html[data-loadmsg]::before { content: "Loading..."; position: fixed; z-index: 99999999; font: 30pt arial; margin: calc(50vh - 1em) calc(50% - 2.5em); background: #ff4500; padding: .5em; border-radius: 10px; box-shadow: 5px 10px rgba(0, 0, 0, .5); } `; var mnuId; function setMnu() { if (window !== window.top) return; try{ if (mnuId) GM_unregisterMenuCommand(mnuId); mnuId=GM_registerMenuCommand('Settings'+(options.misc_disLLPstatus? ': LLP '+(options.enable_LLP?'on':'off')+' ' :'')+(Object.keys(updated).length ?' (new option)':''), function(){ setOptions(); }); }catch(e){} } if (window === window.top) setMnu(); var dlg=false; function setOptions() { if (dlg) return; let k, now=Date.now(); for (k in updated) { if (!updated[k]) updated[k]=now; else if ( (updated[k] + showNew) < now ) delete updated[k]; } if (k) saveOpts(); dlg=document.createElement('div'); dlg.id='triggerLLP-dialog'; dlg.className="triggerLLP-bg"; dlg.innerHTML=`<style> #triggerLLP-options { position: relative; --margins: 40px; max-height: calc( 100vh - 2 * var(--margins) ); max-width: 530px; margin: var(--margins) auto; background: var( --color-neutral-background, var(--color-tone-8, white) ); border: 2px solid gray; box-shadow: var( --boxshadow-modal ); box-sizing: border-box; } html > body:not(.res-console-open) #RESNotifications, html >body:not(.res-console-open) #RESShortcutsAddFormContainer, html > body:not(.res-console-open) .RESDropdownList, html > body:not(.res-console-open):not(.modal-open) .side #search { z-index: 2147483646!important; } .triggerLLP-bg { position: fixed; z-index: 2147483647; width: calc( 100vw + 40px); height: 100vh; top: 0; left: 0; overflow: auto; overscroll-behavior: contain; } span.tLLP-close { position: absolute; right: 5px; top: 5px; border-radius: 15px; width: 30px; height: 23px; text-align: center; padding-top: 7px; background: var( --color-interactive-background-disabled ); cursor: pointer; } span.tLLP-close:hover { background: var(--color-button-plain-background-hover); } span.tLLP-close svg { pointer-events: none; } #triggerLLP-options h2 { font-size: revert; background: var( --color-secondary-background-selected, lightgray); height: 40px; min-height: 40px; margin: 0; padding-left: 2em; line-height: 1.5em; } #triggerLLP-options .content { padding: 1em; margin: 0; overflow: auto; height: 100%; overscroll-behavior: contain; } #triggerLLP-options input { margin: 0; margin-right: 1em; } #triggerLLP-options div { line-height: 1.5em !important; } #triggerLLP-options .empty { margin-bottom: 1em; } #triggerLLP-options { display: flex; flex-direction: column; pointer-events: initial; } #triggerLLP-options .buttons { background: var( --color-secondary-background-selected, lightgray); padding: 0.5em; text-align: center; font-size: small; } #triggerLLP-options button, #triggerLLP-options fieldset, #triggerLLP-options legend { margin: revert; padding: revert; border: revert; vertical-align: revert; } html.theme-light #triggerLLP-options button { background: revert; color: revert; } html.theme-light #triggerLLP-options input[type="text"] { border: revert; } #triggerLLP-dialog .cont { position: fixed; width: calc( 100vw - 18px ); pointer-events: none; } #triggerLLP-dialog:not(.noblur) .cont { backdrop-filter: blur(1px); } #triggerLLP-dialog.diff input, #triggerLLP-dialog.diff span.diff { position: relative; } #triggerLLP-dialog.diff input[type="checkbox"]:not(:disabled):checked:not([data-checked])::before, #triggerLLP-dialog.diff input[type="checkbox"]:not(:disabled)[data-checked]:not(:checked)::before, #triggerLLP-dialog.diff span:first-child.diff:not(:has(+ :disabled))::before { color: red; content: "*"; left: -.5em; position: absolute; } #triggerLLP-dialog.diff input[type="checkbox"]:not(:disabled):checked:not([data-o_checked])::after, #triggerLLP-dialog.diff input[type="checkbox"]:not(:disabled)[data-o_checked]:not(:checked)::after, #triggerLLP-dialog.diff input:not(:disabled) + span.diff::after { color: green; content: "*"; right: -.5em; position: absolute; } #triggerLLP-dialog.diff input + span.diff::after { left: -.8em; right: unset; } #triggerLLP-dialog.diff.rst span.diff { cursor: pointer; } #triggerLLP-dialog:not(.rst) span.diff, #triggerLLP-dialog:not(.rst) input::after, #triggerLLP-dialog:not(.rst) input::before { pointer-events: none; } #triggerLLP-dialog :disabled ~ *, #triggerLLP-dialog :has(~ :disabled) { color: gray; } #triggerLLP-dialog a { color: #3a80e9; text-decoration: revert; } #triggerLLP-dialog a:hover { color: #47b0db; } body[class]:not([class=""]) #triggerLLP-options input[type="text"] { padding: 0; } body[class]:not([class=""]) #triggerLLP-dialog { font-family: IBMPlexSans, Arial, sans-serif !important; font-size: 16px !important; } body[class]:not([class=""]) #triggerLLP-dialog :not(input[type="text"]):not(h2):not(code) { font: inherit; text-transform: none; letter-spacing: unset; } #triggerLLP-options label { color: inherit; } #triggerLLP-options .item { display: flex; align-items: baseline; } #triggerLLP-dialog.nolabel label { pointer-events: none; } #triggerLLP-options code { font: revert; } #triggerLLP-options version { float: right; } #triggerLLP-options #dismiss { float: right; font-size: small; cursor: pointer; } #triggerLLP-options .content.noNew div:has(>[new]) { display: none; } `+( Object.keys(updated).length ? '#triggerLLP-options .content:not(.noNew) div:has(> :is([new], ['+Object.keys(updated).join('], [')+'])) { background: rgba(255, 69, 0, .3); }':` #triggerLLP-options div:has(>[new]) { display: none; } ` )+`</style> <div class="cont"> <div id="triggerLLP-options"> <span class="tLLP-close"><svg fill="currentColor" height="16" viewBox="0 0 20 20" width="16"> <path d="m18.442 2.442-.884-.884L10 9.116 2.442 1.558l-.884.884L9.116 10l-7.558 7.558.884.884L10 10.884l7.558 7.558.884-.884L10.884 10l7.558-7.558Z"></path> </svg></span> <h2>Fix "New" Reddit - Userscript options</h2> <diV class="content"> </div> <div class="buttons"><div><button class="tLLP-save">Save</button> <button class="tLLP-close">Cancel</button> <button class="tLLP-reset">Reset</button> <button class="tLLP-defaults">Defaults</button></div></div> </div> </div> <div style="min-height:101vh;"></div>`; document.body.appendChild(dlg); var c=dlg.querySelector('.content'); if (c) fillContent(); function fillContent(opts = options) { let s=''; for (let v of dlgT) { let k =v[0]; if (k == '-') s+='<div class="empty">'+(v[1]||'')+'</div>'; else if (k == '') s+='<div>'+v[1]+'</div>'; else if (k == '{') s+='<fieldset>'+(v[1]?'<legend>'+v[1]+'</legend>':''); else if (k == '}') s+='</fieldset>'; else { s+='<div class="item"><span></span><input type="'+v[2]+'" name="'+v[0]+'" '+ (typeof opts[k] == 'boolean' ? 'id="'+v[0]+'"'+( opts[k] ? 'checked ':'') + (options[k] ? 'data-checked ':'') + (defOpts[k] ? 'data-o_checked ':'') :'value="'+opts[k]+'" data-value="'+options[k]+'" data-o_value="'+defOpts[k]+'" ')+ (v[3] ? v[3].join(' ') : '')+ '><span></span><label for="'+v[0]+'">'+v[1]+'</label></div>'; } } c.innerHTML='<form onsubmit="return false">'+s+'</form>'; dlg.classList.toggle('diff', options.misc_mark); dlg.classList.toggle('rst', options.misc_rst_o); dlg.classList.toggle('nolabel', options.misc_nolabel); dlg.classList.toggle('noblur', options.misc_noblur); dlg.querySelectorAll('input[type="text"]').forEach(txt_diff); } dlg.addEventListener('click', hevents); dlg.addEventListener('change', hevents); function hevents(ev){ var t=ev.target; if (t.className == 'tLLP-close') { dlg.remove(); dlg=undefined; } else if (t.className == 'tLLP-save') { let newOpts=JSON.parse(JSON.stringify(options)); dlg.querySelectorAll('[name]').forEach(function(k){ if (k.name in defOpts) { if (typeof defOpts[k.name] == 'boolean') newOpts[k.name]=k.checked; else newOpts[k.name]=k.value; } }); saveOpts(newOpts); getOpts(); dlg.remove(); dlg=undefined; setMnu(); for (let i in ML) ML[i].style.display=options[i] ? 'none' : ''; } else if (t.className == 'tLLP-reset') { fillContent(); } else if (t.className == 'tLLP-defaults') { fillContent(defOpts); } else if ( (t.tagName == 'INPUT') && (t.type == 'text') ) { txt_diff(t); } else if ( (t.tagName == 'INPUT') && (t.name=='misc_mark') ) { dlg.classList.toggle('diff', t.checked); } else if ( (t.tagName == 'INPUT') && (t.name=='misc_rst_o') ) { dlg.classList.toggle('rst', t.checked); } else if ( (t.tagName == 'INPUT') && (t.name=='misc_nolabel') ) { dlg.classList.toggle('nolabel', t.checked); } else if ( (t.tagName == 'INPUT') && (t.name=='misc_noblur') ) { dlg.classList.toggle('noblur', t.checked); } else if ( (t.tagName == 'SPAN') && t.classList.contains('cur') ) { t.nextElementSibling.value=t.nextElementSibling.dataset.value; txt_diff(t.nextElementSibling); } else if ( (t.tagName == 'SPAN') && t.classList.contains('def') ) { t.previousElementSibling.value=t.previousElementSibling.dataset.o_value; txt_diff(t.previousElementSibling); } else if (t.id == 'dismiss') { updated={}; saveOpts(); c.classList.add('noNew'); setMnu(); } if (t.dataset.grp) { let a=t.closest('form').querySelectorAll('[data-grp="'+t.dataset.grp+'"]').forEach(function(e){ if (e != t) e.checked=false; }); } } function txt_diff(e) { e.previousElementSibling.classList.toggle('diff', e.value != e.dataset.value); e.previousElementSibling.classList.toggle('cur', e.value != e.dataset.value); e.nextElementSibling.classList.toggle('diff', e.value != e.dataset.o_value); e.nextElementSibling.classList.toggle('def', e.value != e.dataset.o_value); } } // Reddit - fix links var isNew = (location.host == "new.reddit.com"); var isWww = (location.host == "www.reddit.com"); var isOld = (location.host == "old.reddit.com"); var isChat = (location.host == "chat.reddit.com"); var AS=HTMLElement.prototype.attachShadow; function fixLinks() { if (isChat && !options.lnk_rw_chat) return; var clicks={}, delay=10000; Ccl(); setTimeout(Ccl,12000); var oldForNew = false, forNew = false; if (options.stay_new || options.stay_new_old) { Gcl(); forNew=document.referrer.startsWith('https://new.reddit.com/'); if (!forNew && options.stay_new_old) forNew=/^https:\/\/old\.reddit\.com\/r\/[^\/]+\/comments\//.test(document.referrer); if (!isNew && !forNew) { forNew=clicks['_staynew_'+location.href]; // if user reloads, reload as New if (forNew) window.addEventListener('unload', function(){ clicks['_staynew_'+location.href]=Date.now(); Scl(); }); } } var onNew = isNew || forNew; var toNew = onNew && !isNew; if (options.force_new) toNew=true; if ( /^\/r\/[^/]+\/comments\/$/.test(location.pathname) || location.href.startsWith('https://www.reddit.com/media') ) toNew=false; if (clicks[location.href]) onNew=true; if (options.mod_fix_modmail && (location.host == "mod.reddit.com") ) onNew=true; if (isOld) { if (forNew && options.stay_new_old && /^\/r\/[^\/]+\/comments\/$/.test(location.pathname) ) oldForNew=true; else return; } if (toNew) { if (location.host.startsWith('www.')) { let L=location.href.replace(/^https:\/\/www\.reddit\./, 'https://new.reddit.'); if (!clicks[L]) { clicks[L]=Date.now(); Scl(); window.stop(); location.host='new.reddit.com'; } } } if (!onNew) return; if (isWww || isChat) { HTMLElement.prototype.attachShadow=function(m){/*[native */ var e=this; e.sr=AS.call(e,m); newObs(e.sr); return e.sr; } } if (document.readyState != 'loading') init(); else { document.addEventListener('DOMContentLoaded', init); window.addEventListener('load', init); } function newObs(r) { var o=new MutationObserver(cb), config = { attributes: false, childList: true, subtree: true}; o.observe(r, config); return o; } var done=false; function init() { if (done) return; done=true; document && document.body && chk(); var obs=newObs(document.body); } function stayNew(ev) { if (this.hostname == 'i.redd.it') clicks['_staynew_https://www.reddit.com/media?url='+ encodeURIComponent(this.href) ]=Date.now(); clicks['_staynew_'+this.href]=Date.now(); Scl(); } function chk(r) { var a=(r||document).getElementsByTagName("a"); if (r && (r.nodeName == 'A')) a=[r, ...a]; for (let i=0,e; e=a[i]; i++) { if (e._fixed) continue; e._fixed=true; if (options.lnk_rm_utm && e.search) { e.search=e.search.replace(/^\?/,'&').replace(/&utm_[^=&]*(?:=[^&]*)/g, '').replace(/^&/, '?'); } if ( (e.hostname == 'i.redd.it') || (e.hostname == 'preview.redd.it') ) { e.rel=e.rel.replace('noreferrer', ''); if (!isNew && options.stay_new) { e.addEventListener('click',stayNew); e.addEventListener('contextmenu',stayNew); } } else if ( !e.hostname.endsWith('redd.it') && !e.hostname.endsWith('reddit.com') ) { if (options.lnk_ext_noref && !(e.rel ||'').includes('noreferrer')) e.rel=(e.rel ||'')+' noreferrer'; } else if (/^https?:\/\/(www\.|mod\.|old\.)?reddit\.com\//.test(e.href)) { if (/sticky\?num/.test(e.href)) continue; if ( e.href.match('^'+location.origin+location.pathname+'(\\?.*)?$') ) { if (options.stay_new) { e.addEventListener('click',stayNew); e.addEventListener('contextmenu',stayNew); } continue; } e.oriHref=e.href; let uLnk=e.classList.contains('_3t5uN8xUmg0TOwRCOGQEcU'); if ( (options.lnk_rw_intf && !uLnk) || (options.lnk_rw_cmt_www && uLnk) || e.classList.contains('_1tpiOc0IxpDU113wUs4zi1') ) e.href=e.href.replace(/^https?:\/\/(www\.)?reddit\.com\//,'https://new.reddit.com/'); if ( (options.lnk_rw_cmt_old && uLnk) || oldForNew ) e.href=e.href.replace(/^https?:\/\/(old\.)?reddit\.com\//,'https://new.reddit.com/'); } } } function cb(mutL) { for(let mut of mutL) { if (mut.type == 'childList') { for (let e,i=0; e=mut.addedNodes[i]; i++) { if (e.nodeType == 1) chk(e); } } } } function Scl() { if (!Object.keys(clicks).length) localStorage.removeItem("__newL__"); else localStorage.setItem("__newL__", JSON.stringify(clicks) ); } function Gcl() { clicks=JSON.parse(localStorage.getItem("__newL__") || '{}'); return clicks; } function Ccl() { Gcl(); var now=Date.now(); for (let k in clicks) { if ( (clicks[k]+delay) < now ) delete clicks[k]; } Scl(); } } // END fixLinks() fixLinks(); // Reddit - trigger LLP var noLLP=false, skipSub=0, fLLP=function(){}, enable_LLPv2 = options.enable_LLPv2_2, enable_LLPv3 = options.enable_LLPv3_2, enable_LLPv4 = options.enable_LLPv4; if (isNew) { fLLP=LLP_sub; if (options.enable_LLP) { if (enable_LLPv2) { if (/^\/r\/[^\/]+\/wiki\//.test(location.pathname)) { noLLP=true; } else if (!location.pathname.endsWith('/submit')) { window.stop(); location=location.origin+'/submit#'+location.href; return; } else if (location.hash) { tryUntil(hideNP); tryUntil(function(){document.title='Reddit';}); skipSub=2; } } if (enable_LLPv4) { enable_LLPv3=true; if ( /^\/r\/[^\/]+\/comments\//.test(location.pathname) ) { fLLP=LLP_cmt; } } if (enable_LLPv3) { if (/^\/r\/[^\/]+\/wiki\//.test(location.pathname)) { noLLP=true; } if (location.pathname.endsWith('/submit')) { skipSub=1; if (location.hash.startsWith('#back')) { tryUntil(hideNP); tryUntil(function(){document.title='Reddit';}); skipSub=2; tit['#back#']='reddit'; if (!options.no_tit) try{ let k=location.href.split('#back#')[1]; document.title=tit['#back#']=sessionStorage.getItem(k) || 'reddit'; sessionStorage.removeItem(k); }catch(e){} } } } if (location.pathname.endsWith('/submit') && !location.hash) { skipSub=1; } } window.addEventListener('load', LLP); if ( (window === window.top) && options.loadMsg && (document.readyState != 'complete') ) { if (document.documentElement) document.documentElement.dataset.loadmsg='true'; else { tryUntil( function(){if (document.readyState != 'complete') document.documentElement.dataset.loadmsg='true';} ); } } } var LMTO=0; function clrLoad(t = 0) { if (LMTO) clearTimeout(LMTO); return LMTO=setTimeout( function(){delete document.documentElement.dataset.loadmsg;} , t); } function hideNP() { if (!options.hide_NP) return; function rmCls() { setTimeout(function(){document.body.classList.remove('trick');}, t); } document.body.classList.add('trick'); let t = (options.timed_LLP ? options.LLP_TO || 1000 : 0)*1 + 10000; if (document.readyState != 'loading') rmCls(); else { window.addEventListener('load', rmCls); } clrLoad(t); } function LLP() { var r=document.querySelector('#SHORTCUT_FOCUSABLE_DIV'); for (let k in r) { if (k.startsWith('__reactEventHandlers$')) { react=k; break; } } if (!react) { clrLoad(); return; } fLLP(); } function LLP_sub() { clrLoad(); if (location.pathname.endsWith('/submit')) ; if (noLLP) return; if (location.pathname.endsWith('/settings/')) return; if (location.pathname.endsWith('/settings')) return; if (location.pathname.startsWith('/message/')) return; if (location.search.includes('styling')) return; // fix no title set in bg win/tab setBgTitle(); if (!options.enable_LLP) return; // find link without sub-R var e, btn; if (enable_LLPv3 && !skipSub) { btn='a[href="/settings"], a[href="/premium"]'; e=document.querySelector(btn); } else { btn='a[href="/submit"]'; e=document.querySelector(btn); } if (!e && !skipSub) { // try to find in drop-down let c=document.querySelector('header button img + i.icon-caret_down, header button svg + i.icon-caret_down, header button i + i.icon-caret_down'); if (c) { c=c.closest('button'); c[react].onMouseDown({target: c}); } e=document.querySelector(btn); } // use "+" icon if (!e && !skipSub) e=document.querySelector('header button:not([role="menuitem"]) > .icon-add'); if (e || skipSub) { if (!skipSub) { hideNP(); tit[location.href]=document.title; e.click(); if (enable_LLPv3) { let key=Math.random(); if (!options.no_tit) try{ sessionStorage.setItem(key, document.title); }catch(e){} history.replaceState({},null, location.origin+'/submit#back#'+key); window.stop(); location.reload(); return; } } findField(); } } function LLP_cmt() { var r=true; try{r=LLP_cmt_all();}catch(e){} if (r) LLP_sub(); } function LLP_cmt_all() { var R; clrLoad(); // post comment - markdown if (R=document.querySelector('[data-testid="post-container"] ~ div .public-DraftEditor-content')) { let b=R.closest('[data-test-id="comment-submission-form-richtext"]'); if (b) b=b.parentElement; if (b) b=b.querySelector('span > button'); if (b) { b.click(); b.click(); } else return true; let e=R.querySelector('.public-DraftStyleDefault-block br[data-text="true"]'); if (!e) return true; e.innerText='o'; R[react].onInput({target:R}) e.innerText=''; R[react].onInput({target:R}) if (e=document.querySelector('button[id="USER_DROPDOWN_ID"]')) {e.click();e.click();} return; } // post comment - fancy pants else if (R=document.querySelector('[data-testid="post-container"] ~ [data-test-id="comment-submission-form-markdown"] textarea')) { console.info('...ok', R); R.value='o'; R[react].onChange({target:R, currentTarget:R}) R.value=''; R[react].onChange({target:R, currentTarget:R}) R[react].onBlur({target:R}); return; } // comment comment - markdown or fancy pants else if (R=document.querySelector('button > .icon-comment')) { // no reply input should be open if (document.querySelector('[data-testid="comment"] ~ div .public-DraftEditor-content')) return true; let b; if (R) b=R.closest('button'); if (b) { //let p=document.documentElement.scrollTop; let bar=b.closest('._3KgrO85L1p9wQbgwG27q4y') || b.parentElement.parentElement; if (bar) bar.classList.add('hideEdit'); //var wsiv=window.scrollIntoView; //window.scrollIntoView=function(){}; b.click(); clrLoad(10000); tryUntil(function(){ //window.scrollTo(p,0); //window.scrollIntoView=wsiv; let e, t=document.querySelector('[data-testid="comment"] ~ div .public-DraftEditor-content'); // markdown if (!t) { t=document.querySelector('[data-testid="comment"] ~ div textarea'); t.value='o'; t[react].onChange({target:t, currentTarget:t}) t.value=''; t[react].onChange({target:t, currentTarget:t}) e=t.closest('[data-test-id="comment-submission-form-markdown"]'); } // fancypants else { t[react].onFocus({target:t}) e=t.querySelector('.public-DraftStyleDefault-block br[data-text="true"]'); e.innerText='o'; t[react].onInput({target:t}) e.innerText=''; t[react].onInput({target:t}) e=t.closest('[data-test-id="comment-submission-form-richtext"]'); } //window.scrollTo(p,0); if (e) e=e.parentElement; if (e) e=e.querySelector('button[type="reset"]'); if (e) e.click(); setTimeout(function(){ if (bar) bar.classList.remove('hideEdit'); },0); clrLoad(); },2,300, LLP_sub ); } return; } return true; } var max=1000; function findField() { if (!max) return; max--; var b=document.querySelector('textarea[placeholder][maxlength="300"][rows="1"]'); if (!b) { setTimeout(findField, 10); return; } let tt; if ( !options.no_tit && (tt=document.querySelector('html head title')) ) { obsTit.observe(tt, {attributes: false, subtree: true, childList: true, characterData: true }); } b.value='e'; b[react].onChange({target:b}); b.value=''; b[react].onChange({target:b}); if (!(skipSub & 1)) setTimeout(function(){ var L; if (enable_LLPv2 && (L=location.hash.substr(1)).startsWith('https://') ) { history.replaceState({},null, L); history.pushState({},null, L); setTimeout(setBgTitle, 2000); history.back(); setTimeout(function(){history.forward();}, 8000); // fix title } else history.back(); clickDiscard(); clrLoad(); }, options.timed_LLP ? options.LLP_TO || 1000 : 0); } var max2=20; function clickDiscard(){ if (!max2) return; max2--; var b=document.querySelector('div[aria-modal="true"] footer button'); if (!b) { setTimeout(clickDiscard, 10); return; } b.click(); } function setBgTitle(x) { if (document.visibilityState != 'hidden') return; if (enable_LLPv2) { if (location.pathname == '/') document.title='Reddit'; else if (location.pathname.startsWith('/user')) document.title=location.pathname.split('/')[2]; else if (/^\/(r\/[^\/])+\//.test(location.pathname) ) document.title=RegExp.$1; } if (location.pathname == '/') return; try{ let t=document.querySelector('h1')?.textContent; if (!t && /^\/r\/[^\/]+\/comments\/./.test(location.pathname) ) t=document.querySelector('[data-adclicklocation="title"]')?.textContent; if (/^\/r\/[^/]+\/wiki\/([^/]+)/.test(location.pathname)) t=null; if (t && (document.title != t) ) document.title = t; }catch(e){} } var title; // monitor title to prevent "submit" to appear function validTit(s) { const S='Submit to |Einreichen bei |Enviar a |Envoyer à |Invia a |Postar no |Enviar para '; const H='|Reddit – Entdecke ohne Ende|Reddit - Dive into anything|Reddit - Explora lo que quieras|Reddit: Explora lo que quieras|Reddit - Explorez sans limite|Reddit - Scopri ciò che ti piace|Reddit - Explore o que quiser|Reddit - Explora tudo o que quiseres'; var RE=new RegExp('^(\([0-9]+\) *)?('+S+(location.pathname=='/' ? '' : H)+')'); return !RE.test(s); } const obsTit=new MutationObserver(function(muts){ if (!tit[location.href] && tit['#back#']) { document.title=tit[location.href]=tit['#back#']; delete tit['#back#']; } if (!title) title=muts[0].addedNodes[0].textContent; var titleOK, skipT=false; for (let t,i=muts.length-1; i >= 0 ; i--) { t=muts[i].addedNodes[0].textContent; if (validTit(t)) { titleOK=t; skipT=(i==muts.length-1); break; } else { let q=RegExp.$1, t=muts[i].removedNodes[0].textContent; if (validTit(t)) titleOK=t.replace(/^(\([0-9]+\) *)?/, q); } } let t=tit[location.href]; if (!t) {this.disconnect()} if (!t || !titleOK) return; if (!skipT) setTimeout(function(){ document.title=titleOK; },0); }); var TO; // Reddit - fix mod log // 0.2 // if on "new" if (isNew) { window.addEventListener('popstate', function(){ setTimeout(selItem, 200); }); const aliases={ '/about/reports': '/about/modqueue', '/about/spam': '/about/modqueue', '/about/edited': '/about/modqueue', '/about/unmoderated': '/about/modqueue', '/about/flair': '/about/userflair', '/about/muted': '/about/banned', '/about/contributors': '/about/banned', '/about/moderators': '/about/banned', '/about/removal': '/about/rules', '/about/emojis': '/about/awards', }; const fixLnks={ '/about/banned': 1, '/about/muted': 1, '/about/contributors': 1, '/about/moderators': 1, '/about/moderators/': 1 }; const w2n = {'approved-users': 'contributors'}; function fixL(e) { let a=(e).getElementsByTagName("a"); for (let i=0,e; e=a[i]; i++) { if (e._modfixed) continue; e._modfixed=true; //let s=e.pathname.replace(/^\/mod\/([^\/]*)\/(.*)/, '/r/$1/about/$2'); let s=e.pathname.replace(/^\/mod\/([^\/]*)\/(.*)/, function(...a){return '/r/'+a[1]+'/about/'+(w2n[a[2]] || a[2]);} ); if (s != e.pathname) { let a=e.cloneNode(true); e.parentNode.insertBefore(a,e); e.remove(); a.pathname=s; a.addEventListener('click', clickItem); } } } function clickItem(ev){ ev.cancelBubble = true; let e=ev.currentTarget; history.pushState({},null, e.href); history.pushState({},null, e.href); //e.firstElementChild.classList.add('_selected'); //sItem=e.firstElementChild; //sItem.classList.add('selected'); //sItem.style="background-color: #FF4500;"; setTimeout(function(){ //history.forward(); //setTimeout(function(){ p.parentNode.querySelectorAll('.selected').forEach( (e) => e.classList.remove('selected') ); },1000); },100); ev.preventDefault(); history.back(); } function selItem() { var RE= /^(\/r\/[^/]+)(\/about\/([^/]*))/.exec(location.pathname); if (!RE) return; if (!mnu) return; var I; if (RE[3]) I= mnu.shadowRoot.querySelector('a[href="'+RE[1]+RE[2]+location.search+'"] > :first-child') || mnu.shadowRoot.querySelector('a[href^="'+RE[1]+RE[2]+'"] > :first-child') || mnu.shadowRoot.querySelector('a[href="'+RE[1]+(aliases[RE[2]] || RE[2])+location.search+'"] > :first-child') || mnu.shadowRoot.querySelector('a[href^="'+RE[1]+(aliases[RE[2]] || RE[2])+'"] > :first-child'); mnu.shadowRoot.querySelectorAll('a > .selected').forEach(function(e){ if (e === I) { I=null; return; } e.classList.remove('selected'); e.style=undefined; }); if (I) { I.classList.add('selected'); I.style="background-color: #FF4500;"; } if (fixLnks[RE[1]]) fixL(mnu.nextElementSibling); } var hpushState=history.pushState; history.pushState=function(a,b,u){ if ( /^\/r\/[^/]+\/about/.test(u) && /^\/r\/[^/]+\/about/.test(location.pathname) ) { if (!mClicked && (location.pathname != u.split('?')[0] ) && u.includes('?')) { arguments[2]=u.replace(/^.*\/about\/[^?]*/, location.pathname); if (!location.search) setTimeout(function(){ history.back(); setTimeout(function(){history.forward()},100); },0); } } mClicked=false; return hpushState.apply(history, arguments); } // find deepest root var R, ML={}; const obsRoot=new MutationObserver(function(muts){ for (let mut of muts) { if (mut.addedNodes.length) { if (R=document.querySelector('#AppRouter-main-content')) { this.disconnect(); o_pg.observe(R, {attributes: false, subtree: false, childList: true}); fixlocs(); return; } } } }); function startObs() {obsRoot.observe(document.body, {attributes: false, subtree: true, childList: true});} if (document.body) startObs(); else { document.addEventListener('DOMContentLoaded', startObs); } function fixlocs(muts){ if (/^\/r\/[^/]+\/about/.test(location.pathname) ) fixMod(); } const o_pg=new MutationObserver(fixlocs); var obsmnu; var mnu, mClicked; function fixMod() { var sItem; mnu=null; function find(muts){ if (mnu) { // verif let e=mnu.shadowRoot.querySelector('a[href^="/mod/"][href$="/log"]'); if (!e) return; obsmnu && obsmnu.disconnect(); var st=document.createElement('style'); mnu.shadowRoot.appendChild(st); st.textContent=` a > .w-xs ~ span.items-center:not(:has( > * )) { overflow: hidden; text-overflow: ellipsis; display: inline !important; line-height: 1.4em; } [data-hide] { opacity: .4; } [data-hide] .selected { background: none !important; } `; function onclk(ev) { console.info(ev, {ev}, {t:this}, {arguments}); if (!sItem) { sItem=mnu.shadowRoot.querySelector('.selected'); } if (sItem) { sItem.classList.remove('selected'); sItem.style=''; } mClicked=ev.currentTarget; sItem=mClicked.firstElementChild; sItem.classList.add('selected'); sItem.style="background-color: #FF4500;"; } function fixLnk() { oFixLnk.observe(mnu.nextElementSibling , {subtree: true, childList: true}); } var oFixLnk=new MutationObserver(function(mutL){ if ( !fixLnks[ location.pathname.replace(/^\/r\/[^/]+/, '') ] ) { this.disconnect(); return; } for(let mut of mutL) { if (mut.type == 'childList') { for (let e,i=0; e=mut.addedNodes[i]; i++) { if (e.nodeType == 1) fixL(e); } } } }); // at load: if ( fixLnks[ location.pathname.replace(/^\/r\/[^/]+/, '') ] ) { fixL(mnu.nextElementSibling); fixLnk(); } let moded=false; if (options.mod_modLog_r) { moded=addItem('a[href^="/mod/"][href$="/log"]', '/about/log', 'mod_modLog_hide') || moded; } if (options.mod_queues_r) { moded=addItem('a[href^="/mod/"][href$="/queue"]', '/about/modqueue', 'mod_queues_hide') || moded; } if (options.mod_uflair_r) { moded=addItem('a[href^="/mod/"][href$="/userflair"]', '/about/userflair', 'mod_uflair_hide') || moded; } if (options.mod_Rules_r) { moded=addItem('a[href^="/mod/"][href$="/rules"]', '/about/rules', 'mod_Rules_hide') || moded; } if (options.mod_RmvR_r) { moded=addItem('a[href^="/mod/"][href$="/saved-responses"]', '/about/removal', 'mod_RmvR_hide', {txt: 'Removal reasons'} ) || moded; } if (options.mod_UMng_r) { moded=addItem('a[href^="/mod/"][href$="/banned"]', '', 'mod_UMng_hide') || moded; moded=addItem('a[href^="/mod/"][href$="/moderators"]', '/about/banned', 'mod_UMng2_hide', {txt: 'User Management', fixLnk: true}) || moded; } if (options.mod_LnF_r) { moded=addItem('a[href^="/mod/"][href$="/lookandfeel"]', '/?styling=true', '', {txt:'Community styling'}) || moded; moded=addItem('a[href^="/mod/"][href$="/lookandfeel"]', '/about/postflair', '', {txt:'Post flair'}) || moded; moded=addItem('a[href^="/mod/"][href$="/lookandfeel"]', '/about/userflair', 'mod_LnF_hide', {txt:'User flair'}) || moded; } if (moded) mnu.shadowRoot.querySelectorAll('a').forEach(function(e){ e.addEventListener('click', onclk, {capture: true}); }); selItem(); function addItem(o, n, hide, more={}) { var e=mnu.shadowRoot.querySelector(o); if (!e) return false; var E, R=e.pathname.split('/')[2]; E=ML[hide]=e.closest('div'); if (n) { var a=E.cloneNode(true); delete a.dataset.hide; a.removeAttribute('style'); E.parentNode.insertBefore(a,E); } E.dataset.hide=hide; if (options[hide]) E.style.display='none'; if (!n) return true; e=a.querySelector('a'); e.target="_self"; var et=e.querySelector('span.items-center'); if (et) { et.querySelectorAll('.text-brand-onBackground').forEach(function(e){e.remove();}); if (more.txt) et.innerHTML=more.txt; et.innerHTML+=' (old)'; } e.href='/r/'+R+n; e.addEventListener('click', clickItem); if (more.fixLnk) e.addEventListener('click', fixLnk); return true; } } else { if (mnu=R.querySelector('mod-nav')) { obsmnu && obsmnu.disconnect(); obsmnu.observe(mnu.shadowRoot, {attributes: false, subtree: true, childList: true}); return true; } } } if(obsmnu) obsmnu.disconnect(); obsmnu=new MutationObserver(find); if (!find(0)) obsmnu.observe(R, {attributes: false, subtree: true, childList: true}); } } // if (isNew) })();