Skip to content

Commit 985fe21

Browse files
committed
Moved <app|env> into window and config into app, deleted restore classic comments code
1 parent 0f7bab0 commit 985fe21

1 file changed

Lines changed: 47 additions & 125 deletions

File tree

youtube-classic/youtube-classic.user.js

Lines changed: 47 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// ==UserScript==
22
// @name YouTube™ Classic 📺 — (Remove rounded design + Return YouTube dislikes)
3-
// @version 2026.1.21.13
3+
// @version 2026.1.21.14
44
// @author Adam Lui, Magma_Craft, Fuim & hoothin
55
// @namespace https://github.com/adamlui
66
// @description Reverts YouTube to its classic design (before all the rounded corners & hidden dislikes) + redirects YouTube Shorts
@@ -33,8 +33,8 @@
3333
(() => {
3434
'use strict'
3535

36-
const app = { symbol: '📺', configKeyPrefix: 'ytClassic' }
37-
const env = {
36+
window.app = { symbol: '📺', configKeyPrefix: 'ytClassic', config: {} }
37+
window.env = {
3838
scriptManager: {
3939
name: (() => { try { return GM_info.scriptHandler } catch (err) { return 'unknown' }})(),
4040
version: (() => { try { return GM_info.version } catch (err) { return 'unknown' }})()
@@ -46,27 +46,38 @@
4646
}
4747
env.scriptManager.supportsTooltips = env.scriptManager.name == 'Tampermonkey'
4848
&& parseInt(env.scriptManager.version.split('.')[0]) >= 5
49-
const config = {}
5049
const settings = {
5150

5251
controls: { // displays top-to-bottom in toolbar menu
53-
disableShorts: { type: 'toggle', label: 'Redirect Shorts', defaultVal: true,
54-
helptip: 'Redirect Shorts to classic wide player' },
55-
shortsBlock: { type: 'toggle', label: 'Hide Shorts', defaultVal: true,
56-
helptip: 'Hide Shorts from appearing in home page + results' },
57-
playablesBlock: { type: 'toggle', label: 'Hide Playables', defaultVal: true,
58-
helptip: 'Hide Playables from appearing in home page' },
59-
adBlock: { type: 'toggle', label: 'Block Ads', defaultVal: false,
60-
helptip: 'Hide ad thumbnails from homepage layouts' },
61-
aiBlock: { type: 'toggle', label: 'Block AI Summaries', defaultVal: true,
62-
helptip: 'Hide AI summaries from video pages' },
63-
notifDisabled: { type: 'toggle', label: 'Mode Notifications', defaultVal: false,
64-
helptip: 'Show notifications when toggling mode/settings' }
52+
disableShorts: {
53+
type: 'toggle', label: 'Redirect Shorts', defaultVal: true,
54+
helptip: 'Redirect Shorts to classic wide player'
55+
},
56+
shortsBlock: {
57+
type: 'toggle', label: 'Hide Shorts', defaultVal: true,
58+
helptip: 'Hide Shorts from appearing in home page + results'
59+
},
60+
playablesBlock: {
61+
type: 'toggle', label: 'Hide Playables', defaultVal: true,
62+
helptip: 'Hide Playables from appearing in home page'
63+
},
64+
adBlock: {
65+
type: 'toggle', label: 'Block Ads', defaultVal: false,
66+
helptip: 'Hide ad thumbnails from homepage layouts'
67+
},
68+
aiBlock: {
69+
type: 'toggle', label: 'Block AI Summaries', defaultVal: true,
70+
helptip: 'Hide AI summaries from video pages'
71+
},
72+
notifDisabled: {
73+
type: 'toggle', label: 'Mode Notifications', defaultVal: false,
74+
helptip: 'Show notifications when toggling mode/settings'
75+
}
6576
},
6677

6778
load(...keys) {
6879
keys.flat().forEach(key =>
69-
config[key] = processKey(key, GM_getValue(`${app.configKeyPrefix}_${key}`, undefined)))
80+
app.config[key] = processKey(key, GM_getValue(`${app.configKeyPrefix}_${key}`, undefined)))
7081
function processKey(key, val) {
7182
const ctrl = settings.controls?.[key]
7283
if (val != undefined && ( // validate stored val
@@ -77,18 +88,18 @@
7788
}
7889
},
7990

80-
save(key, val) { GM_setValue(`${app.configKeyPrefix}_${key}`, val) ; config[key] = val },
91+
save(key, val) { GM_setValue(`${app.configKeyPrefix}_${key}`, val) ; app.config[key] = val },
8192

8293
typeIsEnabled(key) { // for menu labels + notifs to return ON/OFF
8394
const reInvertSuffixes = /disabled|hidden/i
8495
return reInvertSuffixes.test(key) // flag in control key name
8596
&& !reInvertSuffixes.test(this.controls[key]?.label || '') // but not in label msg key name
86-
? !config[key] : config[key] // so invert since flag reps opposite type state, else don't
97+
? !app.config[key] : app.config[key] // so invert since flag reps opposite type state, else don't
8798
}
8899
}
89100
settings.load(Object.keys(settings.controls))
90101

91-
const domSelectors = {
102+
app.selectors = { site: {
92103
ad: { masthead: 'div#masthead-ad' }, // https://imgur.com/a/kOWzh3O
93104
ai: {
94105
askBtn: 'button:has(path[d*=M480-80q0-83])',
@@ -102,7 +113,7 @@
102113
results: 'grid-shelf-view-model:has(a[href*="/shorts/"])' // https://imgur.com/a/vVzoEfH
103114
}
104115
}
105-
}
116+
}}
106117

107118
const CONFIGS = { BUTTON_REWORK: false }
108119

@@ -308,18 +319,18 @@
308319
const menuLabel = `${
309320
ctrl.symbol || this.state.symbols[+settings.typeIsEnabled(key)] } ${ctrl.label} ${
310321
ctrl.type == 'toggle' ? this.state.separator + this.state.words[+settings.typeIsEnabled(key)]
311-
: ctrl.type == 'slider' ? ': ' + config[key] + ctrl.labelSuffix || ''
322+
: ctrl.type == 'slider' ? ': ' + app.config[key] + ctrl.labelSuffix || ''
312323
: ctrl.status ? ` — ${ctrl.status}` : '' }`
313324
return GM_registerMenuCommand(menuLabel, () => {
314-
settings.save(key, !config[key]) ; syncConfigToUI({ updatedKey: key })
325+
settings.save(key, !app.config[key]) ; syncConfigToUI({ updatedKey: key })
315326
notify(`${ctrl.label}: ${this.state.words[+settings.typeIsEnabled(key)]}`)
316327
}, env.scriptManager.supportsTooltips ? { title: ctrl.helptip || ' ' } : undefined)
317328
})
318329
}
319330
}
320331

321332
function notify(msg, pos = '', notifDuration = '', shadow = '') { // requires dom.js
322-
if (config.notifDisabled && !msg.includes(settings.controls.notifDisabled.label)) return
333+
if (app.config.notifDisabled && !msg.includes(settings.controls.notifDisabled.label)) return
323334

324335
// Strip state word to append colored one later
325336
const foundState = toolbarMenu.state.words.find(word => msg.includes(word))
@@ -343,13 +354,13 @@
343354

344355
function syncConfigToUI(options) {
345356
if (options?.updatedKey == 'disableShorts') {
346-
if (config.disableShorts && !checkShortsToRedir.id)
357+
if (app.config.disableShorts && !checkShortsToRedir.id)
347358
checkShortsToRedir()
348-
else if (!config.disableShorts && checkShortsToRedir.id) {
359+
else if (!app.config.disableShorts && checkShortsToRedir.id) {
349360
cancelAnimationFrame(checkShortsToRedir.id) ; checkShortsToRedir.id = null }
350361
} else if (options?.updatedKey.includes('Block'))
351-
window.configStyle.textContent = Object.entries(domSelectors)
352-
.map(([key, selectors]) => !config[`${key}Block`] ? ''
362+
app.styles.config.textContent = Object.entries(app.selectors.site)
363+
.map(([key, selectors]) => !app.config[`${key}Block`] ? ''
353364
: `${css.selectors.extract(selectors).join(',')} { display: none }`
354365
).join('')
355366
toolbarMenu.refresh() // prefixes/suffixes
@@ -462,95 +473,6 @@
462473
document.querySelector('#items > ytd-mini-guide-entry-renderer:nth-child(2)').data = trendingData
463474
}
464475

465-
// Restore classic comments UI
466-
let hl
467-
const cfconfig = { unicodeEmojis: false }
468-
const cfi18n = { en: {
469-
viewSingular: 'View reply',
470-
viewMulti: 'View %s replies',
471-
viewSingularOwner: 'View reply from %s',
472-
viewMultiOwner: 'View %s replies from %s and others',
473-
hideSingular: 'Hide reply',
474-
hideMulti: 'Hide replies',
475-
replyCntIsolator: /( REPLIES)|( REPLY)/
476-
}}
477-
function getString(string, hl = 'en', ...args) {
478-
if (!string) return
479-
let str
480-
if (cfi18n[hl]) {
481-
if (cfi18n[hl][string]) str = cfi18n[hl][string]
482-
else if (cfi18n.en[string]) str = cfi18n.en[string]
483-
else return
484-
} else if (cfi18n.en[string]) str = cfi18n.en[string]
485-
for (const arg of args) str = str.replace(/%s/, arg)
486-
return str
487-
}
488-
function getSimpleString(object) {
489-
if (object.simpleText) return object.simpleText
490-
let str = ''
491-
for (const run of object.runs) str += run.text
492-
return str
493-
}
494-
function formatComment(comment) {
495-
if (cfconfig.unicodeEmojis) {
496-
try { for (const run of comment.contentText.runs) { delete run.emoji ; delete run.loggingDirectives }}
497-
catch (err) {}
498-
}
499-
return comment
500-
}
501-
async function formatCommentThread(thread) {
502-
if (thread.comment.commentRenderer)
503-
thread.comment.commentRenderer = formatComment(thread.comment.commentRenderer)
504-
let replies
505-
try {
506-
replies = thread.replies.commentRepliesRenderer
507-
if (replies.viewRepliesIcon) {
508-
replies.viewReplies.buttonRenderer.icon = replies.viewRepliesIcon.buttonRenderer.icon
509-
delete replies.viewRepliesIcon
510-
}
511-
if (replies.hideRepliesIcon) {
512-
replies.hideReplies.buttonRenderer.icon = replies.hideRepliesIcon.buttonRenderer.icon
513-
delete replies.hideRepliesIcon
514-
}
515-
let creatorName
516-
try {
517-
creatorName = replies.viewRepliesCreatorThumbnail.accessibility.accessibilityData.label
518-
delete replies.viewRepliesCreatorThumbnail
519-
} catch (err) {}
520-
let replyCnt = getSimpleString(replies.viewReplies.buttonRenderer.text)
521-
replyCnt = +replyCnt.replace(getString('replyCntIsolator', hl), '')
522-
const viewMultiStr = creatorName ? 'viewMultiOwner' : 'viewMulti',
523-
viewSingleStr = creatorName ? 'viewSingularOwner' : 'viewSingular'
524-
replies.viewReplies.buttonRenderer.text = {
525-
runs: [{
526-
text: (replyCnt > 1) ? getString(viewMultiStr, hl, replyCnt, creatorName)
527-
: getString(viewSingleStr, hl, creatorName)
528-
}]
529-
}
530-
replies.hideReplies.buttonRenderer.text = {
531-
runs: [{ text: (replyCnt > 1) ? getString('hideMulti', hl) : getString('hideSingular', hl) }]
532-
}
533-
} catch (err) {}
534-
return thread
535-
}
536-
function refreshData(elem) {
537-
const clone = elem.cloneNode()
538-
clone.data = elem.data ; clone.data.fixedByCF = true
539-
for (const i in elem.properties) clone[i] = elem[i]
540-
elem.insertAdjacentElement('afterend', clone) ; elem.remove()
541-
}
542-
const commentObserver = new MutationObserver(mutations => mutations.forEach(async mutation => {
543-
if (mutation.addedNodes) for (const elem of mutation.addedNodes) if (elem.classList && !elem.data?.fixedByCF)
544-
if (elem.tagName == 'YTD-COMMENT-THREAD-RENDERER') {
545-
elem.data = await formatCommentThread(elem.data)
546-
refreshData(elem)
547-
} else if (elem.tagName == 'YTD-COMMENT-RENDERER'
548-
&& !elem.classList.contains('ytd-comment-thread-renderer')
549-
) { elem.data = formatComment(elem.data) ; refreshData(elem) }
550-
}))
551-
document.addEventListener('yt-page-data-updated', async () =>
552-
commentObserver.observe(document.querySelector('ytd-app'), { childList: true, subtree: true }))
553-
554476
// CSS adjustments and UI fixes
555477
app.styles = { fixes: dom.create.style(`
556478
yt-thumbnail-view-model { border-radius: 0 !important } /* square homepage thumbs */
@@ -1122,7 +1044,7 @@
11221044
const obsConfig = { childList: true, subtree: true }
11231045

11241046
// Redirect Shorts to classic player
1125-
if (config.disableShorts) checkShortsToRedir()
1047+
if (app.config.disableShorts) checkShortsToRedir()
11261048
function checkShortsToRedir() {
11271049
if (location.pathname.startsWith('/shorts/'))
11281050
return location.replace(`https://www.youtube.com/watch?v=${location.pathname.split('/')[2]}`)
@@ -1135,19 +1057,19 @@
11351057
locationPath = location.pathname ; homeObserver.disconnect()
11361058
dom.get.loadedElem('html').then(() => homeObserver.observe(document.documentElement, obsConfig))
11371059
} else if (locationPath == '/') { // remove regenerating homepage stuff
1138-
if (config.adBlock) // remove ads
1060+
if (app.config.adBlock) // remove ads
11391061
document.querySelector('ytd-ad-slot-renderer')?.closest('[rendered-from-rich-grid]')?.remove()
1140-
if (config.shortsBlock || config.playablesBlock) // remove shelves
1062+
if (app.config.shortsBlock || app.config.playablesBlock) // remove shelves
11411063
document.querySelector(
1142-
`ytd-rich-section-renderer${ !config.shortsBlock ? ':not(:has(a[href*="/shorts/"]))' : '' }${
1143-
!config.playablesBlock ? ':not(:has(a[href*="/playables/"]))' : '' }`
1064+
`ytd-rich-section-renderer${ !app.config.shortsBlock ? ':not(:has(a[href*="/shorts/"]))' : '' }${
1065+
!app.config.playablesBlock ? ':not(:has(a[href*="/playables/"]))' : '' }`
11441066
)?.remove()
11451067
}
11461068
})
11471069
dom.get.loadedElem('html').then(() => homeObserver.observe(document.documentElement, obsConfig))
11481070

11491071
// Block stuff
1150-
document.head.append(window.configStyle ??= dom.create.style())
1151-
window.configStyle.textContent = Object.entries(domSelectors).map(([key, selectors]) =>
1152-
!config[`${key}Block`] ? '' : `${css.selectors.extract(selectors).join(',')} { display: none }`).join('')
1072+
document.head.append(app.styles.config ??= dom.create.style())
1073+
app.styles.config.textContent = Object.entries(app.selectors.site).map(([key, selectors]) =>
1074+
!app.config[`${key}Block`] ? '' : `${css.selectors.extract(selectors).join(',')} { display: none }`).join('')
11531075
})()

0 commit comments

Comments
 (0)