Skip to content

Instantly share code, notes, and snippets.

@RVZO6
Last active December 7, 2025 16:22
Show Gist options
  • Select an option

  • Save RVZO6/c6c1a3ed69d46afeff7d0ac7503296bd to your computer and use it in GitHub Desktop.

Select an option

Save RVZO6/c6c1a3ed69d46afeff7d0ac7503296bd to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name YouTube Focus Mode (Zen Workspaces)
// @description Minimalist blocking. No distractions.
// @version 3.0
// ==/UserScript==
(function () {
'use strict';
// settings
const PREFS = {
workspaces: 'youtube.focus.blocked_workspaces',
msg: 'youtube.focus.message',
color: 'youtube.focus.text_color',
color_dark: 'youtube.focus.text_color_dark',
size: 'youtube.focus.font_size',
weight: 'youtube.focus.font_weight',
font: 'youtube.focus.font_family',
};
const DEFAULTS = {
workspaces: 'Work',
msg: 'lock in brochacho',
color: '#000',
color_dark: '#FFF',
size: '24px',
weight: '400',
font: 'Comic Sans MS, system-ui, sans-serif',
};
// the css
const CSS_STATIC = `
:root {
--zf-msg: ""; --zf-color: #555; --zf-color-dark: #e0e0e0;
--zf-size: 24px; --zf-weight: 400; --zf-font: system-ui;
}
/* hide distractions */
body.zen-active #secondary,
body.zen-active #related,
body.zen-active #comments,
body.zen-active ytd-reel-shelf-renderer,
body.zen-active ytd-shorts,
body.zen-active .ytp-endscreen-content,
body.zen-active .ytp-ce-element,
body.zen-active ytd-browse[page-subtype="home"] #contents {
display: none !important;
}
/* show message (home only) */
body.zen-active ytd-browse[page-subtype="home"]::after {
content: var(--zf-msg);
position: fixed; top: 50%; left: 50%;
transform: translate(-50%, -50%);
color: var(--zf-color);
font-size: var(--zf-size);
font-weight: var(--zf-weight);
font-family: var(--zf-font);
z-index: 9999; pointer-events: none;
text-align: center; white-space: pre-wrap;
}
/* dark mode */
html[dark] body.zen-active ytd-browse[page-subtype="home"]::after {
color: var(--zf-color-dark);
}
`;
// helpers
const getPref = (k) => {
try { return Services.prefs.getStringPref(PREFS[k]); }
catch { return DEFAULTS[k]; }
};
const shouldBlock = () => {
const current = window.gZenWorkspaces?.getActiveWorkspaceFromCache()?.name?.toLowerCase();
return current && getPref('workspaces').toLowerCase().split(',').map(s => s.trim()).includes(current);
};
// frame script
const FRAME_SCRIPT = `
(function() {
const STYLE_ID = 'zen-focus-style';
const CSS = ${JSON.stringify(CSS_STATIC)};
function update(data) {
if (!content?.location?.host?.includes('youtube.com') || !content?.document?.body) return;
const doc = content.document;
if (!doc.getElementById(STYLE_ID)) {
const s = doc.createElement('style');
s.id = STYLE_ID; s.textContent = CSS;
doc.head.appendChild(s);
}
const s = doc.documentElement.style;
s.setProperty('--zf-msg', JSON.stringify(data.cfg.msg));
s.setProperty('--zf-color', data.cfg.color);
s.setProperty('--zf-color-dark', data.cfg.color_dark);
s.setProperty('--zf-size', data.cfg.size);
s.setProperty('--zf-weight', data.cfg.weight);
s.setProperty('--zf-font', data.cfg.font);
doc.body.classList.toggle('zen-active', data.active);
}
addMessageListener('YouTubeFocus:Update', m => update(m.data));
const notify = () => {
if (content?.location?.host?.includes('youtube.com')) sendAsyncMessage('YouTubeFocus:Ready');
};
addEventListener('DOMContentLoaded', notify, true);
addEventListener('yt-navigate-finish', notify, true);
})();
`;
// main process
const pushState = (browser) => {
if (!browser?.messageManager || !browser.currentURI?.host?.includes('youtube.com')) return;
const cfg = {
msg: getPref('msg'), color: getPref('color'), color_dark: getPref('color_dark'),
size: getPref('size'), weight: getPref('weight'), font: getPref('font'),
};
browser.messageManager.sendAsyncMessage('YouTubeFocus:Update', { active: shouldBlock(), cfg });
};
const broadcast = () => {
if (gBrowser) gBrowser.tabs.forEach(tab => pushState(tab.linkedBrowser));
};
async function init() {
Object.entries(PREFS).forEach(([k, v]) => {
if (!Services.prefs.prefHasUserValue(v)) Services.prefs.setStringPref(v, DEFAULTS[k]);
Services.prefs.addObserver(v, broadcast);
});
while (!window.gZenWorkspaces) await new Promise(r => setTimeout(r, 100));
window.messageManager.loadFrameScript('data:,' + encodeURIComponent(FRAME_SCRIPT), true);
window.messageManager.addMessageListener('YouTubeFocus:Ready', m => pushState(m.target));
window.addEventListener('ZenWorkspacesUIUpdate', broadcast);
gBrowser.tabContainer.addEventListener('TabSelect', () => pushState(gBrowser.selectedBrowser));
broadcast();
}
if (document.readyState === 'complete') init();
else window.addEventListener('load', init, { once: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment