Merge main into released

This commit is contained in:
Lawrence Hook
2026-02-04 20:11:53 -05:00
14 changed files with 220 additions and 143 deletions
+1
View File
@@ -2,3 +2,4 @@ keys/
web-ext-artifacts/ web-ext-artifacts/
extension.zip extension.zip
manifest.json manifest.json
_scratch/
+3 -17
View File
@@ -1,31 +1,17 @@
# TODO # TODO
## Quick Wins
| Issue | Effort |
|-------|--------|
| Remove debug `console.log` in `options/main.js:174-175` | 1 min |
| Sync manifest versions (4.3.65 vs 4.3.66) | 1 min |
| Delete unused `TEMPLATE_FIELDSET` in `options/main.js:8` | 1 min |
| Delete dead `setCookie`/`getCookie` in `content-script/main.js:657-678` | 1 min |
| Fix `SEC_IN_WEEK` naming in `utils.js:69` (it's actually minutes) | 1 min |
| Move duplicated regexes to `shared/utils.js` | 5 min |
| Delete commented-out code blocks in `content-script/main.js` | 5 min |
| Add Page Visibility API to pause polling when tab is hidden | 10 min |
## Code Quality ## Code Quality
- [ ] Auto-generate `idToShortId` map from `SECTIONS` instead of manual maintenance - [ ] Auto-generate `idToShortId` map from `SECTIONS` instead of manual maintenance
- [ ] Add storage validation/migration for schema changes between versions - [ ] Add storage validation/migration for schema changes between versions
- [ ] Improve error handling beyond `console.log(error)` - [ ] Improve error handling beyond `console.log(error)`
- [ ] Clean up event listeners in `options/main.js` to prevent memory leaks
## i18n / Localization ## i18n / Localization
Hardcoded English strings that break for non-English YouTube: Hardcoded English strings that break for non-English YouTube:
- `content-script/main.js:171``'for you'` comparison - `content-script/main.js``'for you'` comparison
- `content-script/main.js:211``'Streamed'` check - `content-script/main.js``'Streamed'` check
- `content-script/main.js:467-468``'All'`, `'Related'` chip names - `content-script/main.js``'All'`, `'Related'` chip names
## Incomplete Features ## Incomplete Features
+1 -1
View File
@@ -3,7 +3,7 @@
"description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.", "description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.",
"homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions", "homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions",
"manifest_version": 3, "manifest_version": 3,
"version": "4.3.68", "version": "4.3.69",
"icons": { "icons": {
"16": "/images/16.png", "16": "/images/16.png",
+55 -96
View File
@@ -10,12 +10,6 @@ const REDIRECT_URLS = {
"redirect_to_library": 'https://www.youtube.com/feed/library', "redirect_to_library": 'https://www.youtube.com/feed/library',
}; };
const resultsPageRegex = new RegExp('.*://.*youtube\.com/results.*', 'i');
const homepageRegex = new RegExp('.*://(www|m)\.youtube\.com(/)?$', 'i');
const shortsRegex = new RegExp('.*://.*youtube\.com/shorts.*', 'i');
const videoRegex = new RegExp('.*://.*youtube\.com/watch\\?v=.*', 'i');
const channelRegex = new RegExp('.*://.*youtube\.com/(@|channel)', 'i');
const subsRegex = new RegExp(/\/feed\/subscriptions$/, 'i');
// Dynamic settings variables // Dynamic settings variables
const cache = {}; const cache = {};
@@ -49,7 +43,7 @@ let theaterClicked = false, hyper = false;
let onResultsPage = resultsPageRegex.test(url); let onResultsPage = resultsPageRegex.test(url);
let onHomepage = homepageRegex.test(url); let onHomepage = homepageRegex.test(url);
let onShorts = shortsRegex.test(url); let onShorts = shortsRegex.test(url);
let onVideo = videoRegex.test(url); let onVideo = videoPageRegex.test(url);
let onChannel = channelRegex.test(url); let onChannel = channelRegex.test(url);
let onSubs = subsRegex.test(url); let onSubs = subsRegex.test(url);
let settingsInit = false let settingsInit = false
@@ -57,8 +51,6 @@ let settingsInit = false
let dynamicIters = 0; let dynamicIters = 0;
let frameRequested = false; let frameRequested = false;
let isRunning = false; let isRunning = false;
// let lastRun = Date.now();
// let counter = 0;
let lastScheduleCheck; let lastScheduleCheck;
const scheduleInterval = 2_000; // 2 seconds const scheduleInterval = 2_000; // 2 seconds
let lastRedirect; let lastRedirect;
@@ -113,8 +105,6 @@ document.addEventListener("DOMContentLoaded", e => handleNewPage());
// Dynamic settings (i.e. js instead of css) // Dynamic settings (i.e. js instead of css)
function runDynamicSettings() { function runDynamicSettings() {
if (isRunning) return; if (isRunning) return;
// console.log('runDynamicSettings', Date.now() - lastRun);
// lastRun = Date.now();
isRunning = true; isRunning = true;
dynamicIters += 1; dynamicIters += 1;
const on = cache['global_enable'] === true; const on = cache['global_enable'] === true;
@@ -204,8 +194,10 @@ function runDynamicSettings() {
} }
} }
// Subscriptions page options // Subscriptions page options (only if any sub-page settings are enabled)
if (onSubs) { const subsSettingsEnabled = cache['remove_sub_shorts'] || cache['remove_sub_live'] ||
cache['remove_sub_upcoming'] || cache['remove_sub_premiere'] || cache['remove_sub_vods'];
if (onSubs && subsSettingsEnabled) {
const badgeSelector = 'ytd-badge-supported-renderer'; const badgeSelector = 'ytd-badge-supported-renderer';
const upcomingBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="UPCOMING"]'; const upcomingBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="UPCOMING"]';
const shortsBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="SHORTS"]'; const shortsBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="SHORTS"]';
@@ -273,13 +265,15 @@ function runDynamicSettings() {
}); });
} }
// Click on "dismiss" buttons // Click on "dismiss" buttons (only check occasionally, not every iteration)
const dismissButtons = qsa('#dismiss-button'); if (dynamicIters % 5 === 0) {
dismissButtons.forEach(dismissButton => { const dismissButtons = qsa('#dismiss-button');
if (dismissButton && dismissButton.offsetParent) { dismissButtons.forEach(dismissButton => {
dismissButton.click(); if (dismissButton && dismissButton.offsetParent) {
} dismissButton.click();
}) }
});
}
// Disable autoplay // Disable autoplay
if (cache['disable_autoplay'] === true) { if (cache['disable_autoplay'] === true) {
@@ -340,16 +334,6 @@ function runDynamicSettings() {
} }
} }
// // Enable theater mode
// if (cache['enable_theater'] === true && !theaterClicked) {
// const theaterButton = qsa('button[title="Theater mode (t)"]')?.[0];
// if (theaterButton && theaterButton.display !== 'none') {
// console.log('theaterButton.click();')
// theaterButton.click();
// theaterClicked = true;
// }
// }
// Skip through ads // Skip through ads
if (cache['auto_skip_ads'] === true) { if (cache['auto_skip_ads'] === true) {
@@ -361,10 +345,7 @@ function runDynamicSettings() {
}); });
// Click on "Skip ad" button // Click on "Skip ad" button
const skipButtons = qsa('.ytp-ad-skip-button'). const skipButtons = qsa('.ytp-ad-skip-button, .ytp-ad-skip-button-modern, .ytp-skip-ad-button, .ytp-skip-ad button');
concat(qsa('.ytp-ad-skip-button-modern')).
concat(qsa('.ytp-skip-ad-button')).
concat(qsa(CSS.escape("button#skip-button:2")));
const skippableAd = skipButtons?.some(button => button.offsetParent); const skippableAd = skipButtons?.some(button => button.offsetParent);
if (skippableAd) { if (skippableAd) {
@@ -409,10 +390,6 @@ function runDynamicSettings() {
} }
} }
// if (cache['change_playback_speed']) {
// document.getElementsByTagName("video")[0].playbackRate = Number(cache['change_playback_speed']);
// }
// Hide all but the timestamped comments // Hide all but the timestamped comments
if (cache['remove_non_timestamp_comments']) { if (cache['remove_non_timestamp_comments']) {
const timestamps = qsa('yt-formatted-string:not(.published-time-text).ytd-comment-renderer > a.yt-simple-endpoint[href^="/watch"]'); const timestamps = qsa('yt-formatted-string:not(.published-time-text).ytd-comment-renderer > a.yt-simple-endpoint[href^="/watch"]');
@@ -422,30 +399,6 @@ function runDynamicSettings() {
}); });
} }
// // Disable play on hover
// if (dynamicIters % 10 === 0) {
// const prefCookie = getCookie('PREF');
// const prefObj = prefCookie?.split('&')?.reduce((acc, x) => {
// const [ key, value ] = x.split('=');
// acc[key] = value;
// return acc;
// }, {});
// if (prefObj) {
// const f7 = prefObj['f7'] || '0';
// const playOnHoverEnabled = f7[f7.length-1] === '0';
// if (cache['disable_play_on_hover'] && playOnHoverEnabled) {
// prefObj['f7'] = f7.substring(0, f7.length-1) + '1';
// const newPref = Object.entries(prefObj).map(([key, value]) => `${key}=${value}`).join('&');
// setCookie('PREF', newPref);
// } else if (!cache['disable_play_on_hover'] && !playOnHoverEnabled) {
// prefObj['f7'] = f7.substring(0, f7.length-1) + '0';
// const newPref = Object.entries(prefObj).map(([key, value]) => `${key}=${value}`).join('&');
// setCookie('PREF', newPref);
// }
// }
// }
// Show description // Show description
if (cache['expand_description'] || cache['remove_comments']) { if (cache['expand_description'] || cache['remove_comments']) {
const expandButton = qsa('#description #expand.button'); const expandButton = qsa('#description #expand.button');
@@ -508,8 +461,8 @@ function runDynamicSettings() {
}); });
} }
// Reveal suggestions boxes // Reveal suggestions boxes (only check on early iterations)
REVEAL_BOX_CONFIGS.forEach(({ containerSelector, boxId, message, showAction, revealSetting }) => { if (dynamicIters <= 30) REVEAL_BOX_CONFIGS.forEach(({ containerSelector, boxId, message, showAction, revealSetting }) => {
if (closedRevealBoxes.has(boxId)) return; if (closedRevealBoxes.has(boxId)) return;
if (qs(`#${boxId}`)) return; if (qs(`#${boxId}`)) return;
@@ -561,9 +514,11 @@ function runDynamicSettings() {
// Video Player: hide the 'clip' button. // Video Player: hide the 'clip' button.
// The path[d=...] selector selects scissor SVGs. // The path[d=...] selector selects scissor SVGs.
qsa('path[d^="M8 7c0 .55-.45 1-1 1s-1-.45-1-1"]'). if (cache['remove_clip_button']) {
map(path => path.closest('#menu button')). qsa('path[d^="M8 7c0 .55-.45 1-1 1s-1-.45-1-1"]').
forEach(b => b.setAttribute('scissor_button', '')); map(path => path.closest('#menu button')).
forEach(b => b?.setAttribute('scissor_button', ''));
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@@ -577,11 +532,35 @@ function runDynamicSettings() {
function requestRunDynamicSettings() { function requestRunDynamicSettings() {
if (frameRequested || isRunning) return; if (frameRequested || isRunning) return;
if (document.hidden) return; // Pause polling when tab is hidden
frameRequested = true; frameRequested = true;
// setTimeout(() => runDynamicSettings(), 50); // Start fast (100ms), slow down to 500ms after page settles
setTimeout(() => runDynamicSettings(), Math.min(100, 50 + 10 * dynamicIters)); const delay = dynamicIters < 20 ? 100 : Math.min(500, 100 + dynamicIters * 10);
setTimeout(() => runDynamicSettings(), delay);
} }
// Resume polling when tab becomes visible
document.addEventListener('visibilitychange', () => {
if (!document.hidden) {
requestRunDynamicSettings();
}
});
function injectAnnouncementBanners() {
if (!onHomepage) return;
if (!document.body) return;
const logoUrl = browser.runtime.getURL('images/rys.svg');
const banners = getActiveBanners('youtube_homepage');
banners.forEach(banner => {
initBanner(banner, logoUrl, () => ({
element: document.body,
insertMethod: 'prepend'
}));
});
}
function injectAnnouncementBanners() { function injectAnnouncementBanners() {
if (!onHomepage) return; if (!onHomepage) return;
@@ -612,13 +591,16 @@ function injectScripts() {
script.type = "text/javascript"; script.type = "text/javascript";
script.innerText = ` script.innerText = `
(function() { (function() {
let pm; let pm, intervalId;
function f() { function f() {
if (!pm) pm = document.querySelector('yt-playlist-manager'); if (!pm) pm = document.querySelector('yt-playlist-manager');
if (pm) pm.canAutoAdvance_ = false; if (pm) {
pm.canAutoAdvance_ = false;
if (intervalId) clearInterval(intervalId);
}
} }
f(); f();
setInterval(f, 100); intervalId = setInterval(f, 100);
})() })()
`; `;
document.body?.appendChild(script); document.body?.appendChild(script);
@@ -637,7 +619,7 @@ function handleNewPage() {
onResultsPage = resultsPageRegex.test(url); onResultsPage = resultsPageRegex.test(url);
onHomepage = homepageRegex.test(url); onHomepage = homepageRegex.test(url);
onShorts = shortsRegex.test(url); onShorts = shortsRegex.test(url);
onVideo = videoRegex.test(url); onVideo = videoPageRegex.test(url);
onChannel = channelRegex.test(url); onChannel = channelRegex.test(url);
onSubs = subsRegex.test(url); onSubs = subsRegex.test(url);
settingsInit = false; settingsInit = false;
@@ -696,29 +678,6 @@ function handleNewPage() {
requestRunDynamicSettings(); requestRunDynamicSettings();
} }
function setCookie(cname, cvalue, exdays=370) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
let expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";domain=.youtube.com;path=/";
}
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function updateSetting(id, value) { function updateSetting(id, value) {
HTML.setAttribute(id, value); HTML.setAttribute(id, value);
cache[id] = value; cache[id] = value;
+1 -1
View File
@@ -3,7 +3,7 @@
"description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.", "description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.",
"homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions", "homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions",
"manifest_version": 2, "manifest_version": 2,
"version": "4.3.68", "version": "4.3.69",
"icons": { "icons": {
"16": "/images/16.png", "16": "/images/16.png",
+70 -1
View File
@@ -390,6 +390,75 @@ html[foo=bar] {
} }
/* Logging Opt-in Banner */
#log_prompt_banner {
position: fixed;
bottom: 8px;
left: 8px;
right: 8px;
z-index: 100;
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: var(--body-color);
border-radius: var(--border-radius);
font-size: 12px;
opacity: 0.9;
}
#log_prompt_banner * {
color: var(--body-background-color);
}
#log_prompt_text {
flex: 1;
}
#log_prompt_buttons {
display: flex;
gap: 6px;
}
#log_prompt_buttons button {
padding: 4px 10px;
border: none;
border-radius: var(--border-radius);
font-size: 12px;
cursor: pointer;
}
#log_prompt_yes {
background-color: var(--body-background-color);
color: var(--body-color) !important;
}
#log_prompt_no {
background-color: transparent;
border: 1px solid var(--box-shadow-color) !important;
}
#log_prompt_buttons button:hover {
opacity: 0.85;
}
#log_prompt_dismiss {
background: none;
border: none;
font-size: 16px;
cursor: pointer;
padding: 0 4px;
opacity: 0.7;
line-height: 1;
}
#log_prompt_dismiss:hover {
opacity: 1;
}
/* Menu Timer */ /* Menu Timer */
#timer_container { #timer_container {
position: fixed; position: fixed;
@@ -439,7 +508,7 @@ html[foo=bar] {
#sidebar { #sidebar {
height: calc(6px + var(--body-height)); height: calc(6px + var(--body-height));
width: 140px; width: 160px;
padding: 8px 6px; padding: 8px 6px;
overflow: hidden; overflow: hidden;
+1 -1
View File
@@ -115,7 +115,7 @@
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="info-label">Screenshot</span> <span class="info-label">Screenshot</span>
<span class="info-value">A visual helps a lot</span> <span class="info-value">If possible, attach a screenshot</span>
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="info-label">Browser</span> <span class="info-label">Browser</span>
+8 -4
View File
@@ -3,13 +3,17 @@
html[dark_mode='false'] { --svg-color: #464646 } html[dark_mode='false'] { --svg-color: #464646 }
html[dark_mode='true'] { --svg-color: #E9E9E9 } html[dark_mode='true'] { --svg-color: #E9E9E9 }
#header-settings circle,
#header-toggle path, #header-toggle path,
.dark_mode circle, .dark_mode path .dark_mode circle, .dark_mode path
{ {
fill: var(--svg-color); fill: var(--svg-color);
} }
#header-settings path,
#header-settings circle {
stroke: var(--svg-color);
}
/* Dark mode styling */ /* Dark mode styling */
html[dark_mode='true'] #header-dark { display: none } html[dark_mode='true'] #header-dark { display: none }
html[dark_mode='false'] #header-light { display: none } html[dark_mode='false'] #header-light { display: none }
@@ -169,9 +173,9 @@ html[foo=bar]
} }
#header-settings { #header-settings {
cursor: pointer; cursor: pointer;
height: var(--icon-dim); height: calc(var(--icon-dim) - 6px);
max-height: var(--icon-dim); max-height: calc(var(--icon-dim) - 6px);
max-width: var(--icon-dim); max-width: calc(var(--icon-dim) - 6px);
} }
#settings-menu { #settings-menu {
font-size: 14px; font-size: 14px;
+14 -6
View File
@@ -121,6 +121,15 @@
</div> </div>
<div id="log_prompt_banner" hidden>
<div id="log_prompt_text">Help improve RYS? Share anonymous usage data to guide development.</div>
<div id="log_prompt_buttons">
<button id="log_prompt_no">No thanks</button>
<button id="log_prompt_yes">Sure</button>
</div>
<button id="log_prompt_dismiss" title="Ask me later"></button>
</div>
<div id="timer_container"> <div id="timer_container">
<div>Menu Timer</div> <div>Menu Timer</div>
<div></div> <div></div>
@@ -142,8 +151,8 @@
<a href='https://www.youtube.com/feed/history' title="Too many cat video suggestions? Try removing cat videos from your watch history." target="_blank">Manage History</a> <a href='https://www.youtube.com/feed/history' title="Too many cat video suggestions? Try removing cat videos from your watch history." target="_blank">Manage History</a>
<a href='https://myactivity.google.com/product/youtube' title="Too many cat video suggestions? Try removing cat videos from your watch history." target="_blank">Manage History — Advanced</a> <a href='https://myactivity.google.com/product/youtube' title="Too many cat video suggestions? Try removing cat videos from your watch history." target="_blank">Manage History — Advanced</a>
<hr> <hr>
<div id='log-enable' title="By default, RYS uses logging to collect statistics about usage. This data helps guide future development of new features. All data is anonymous, not shared with 3rd parties, and I am committed to users' privacy. You currently have logging disabled, if you'd like to re-enable it click here.">Re-enable logging</div> <div id='log-enable' title="RYS can collect anonymous usage statistics to help guide future development. All data is anonymous and not shared with 3rd parties. Click here to enable logging.">Enable logging</div>
<div id='log-disable' title="By default, RYS uses logging to collect statistics about usage. This data helps guide future development of new features. All data is anonymous, not shared with 3rd parties, and I am committed to users' privacy. To disable logging, click here.">Opt-out of logging</div> <div id='log-disable' title="RYS collects anonymous usage statistics to help guide future development. All data is anonymous and not shared with 3rd parties. Click here to disable logging.">Disable logging</div>
<hr> <hr>
<a href='https://github.com/lawrencehook/remove-youtube-suggestions' target='_blank'>View Source Code</a> <a href='https://github.com/lawrencehook/remove-youtube-suggestions' target='_blank'>View Source Code</a>
<a href='https://docs.google.com/forms/d/1AzQQxTWgG6M5N87jinvXKQkGS6Mehzg19XV4mjteTK0' target='_blank'>Give Feedback</a> <a href='https://docs.google.com/forms/d/1AzQQxTWgG6M5N87jinvXKQkGS6Mehzg19XV4mjteTK0' target='_blank'>Give Feedback</a>
@@ -203,10 +212,9 @@
</a> </a>
</div> </div>
<svg id='header-settings' viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" fill="black"> <svg id='header-settings' viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="black" stroke-width="1.5">
<circle cx="12" cy="32" r="7"/> <circle cx="12" cy="12" r="3"/>
<circle cx="52" cy="32" r="7"/> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
<circle cx="32" cy="32" r="7"/>
</svg> </svg>
</div> </div>
+51 -10
View File
@@ -5,7 +5,6 @@ const HTML = document.documentElement;
const SIDEBAR = document.getElementById('sidebar'); const SIDEBAR = document.getElementById('sidebar');
const TEMPLATE_SIDEBAR_SECTION = document.getElementById('template_sidebar_section'); const TEMPLATE_SIDEBAR_SECTION = document.getElementById('template_sidebar_section');
const OPTIONS_LIST = document.getElementById('primary_options'); const OPTIONS_LIST = document.getElementById('primary_options');
const TEMPLATE_FIELDSET = document.getElementById('template_fieldset');
const TEMPLATE_SECTION = document.getElementById('template_section'); const TEMPLATE_SECTION = document.getElementById('template_section');
const TEMPLATE_OPTION = document.getElementById('template_option'); const TEMPLATE_OPTION = document.getElementById('template_option');
const TIMER_CONTAINER = document.getElementById('timer_container'); const TIMER_CONTAINER = document.getElementById('timer_container');
@@ -13,12 +12,6 @@ const LOCK_CODE_CONTAINER = document.getElementById('lock_code_container');
let openedTime = Date.now(); let openedTime = Date.now();
let currentUrl; let currentUrl;
const resultsPageRegex = new RegExp('.*://.*youtube\\.com/results.*', 'i');
const videoPageRegex = new RegExp('.*://(www|m)\\.youtube\\.com/watch\\?v=.*', 'i');
const homepageRegex = new RegExp('.*://(www|m)\\.youtube\\.com/$', 'i');
const channelRegex = new RegExp('.*://.*youtube\.com/(@|channel)', 'i');
const shortsRegex = new RegExp('.*://.*youtube\.com/shorts.*', 'i');
const subsRegex = new RegExp(/\/feed\/subscriptions$/, 'i');
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
recordEvent('Page View: Options'); recordEvent('Page View: Options');
@@ -35,6 +28,11 @@ document.addEventListener("DOMContentLoaded", () => {
return acc; return acc;
}, {}); }, {});
// Show logging opt-in modal if user hasn't responded yet
if (!localSettings.log_prompt_answered) {
showLogPrompt();
}
browser.tabs.query({ currentWindow: true, active: true }, tabs => { browser.tabs.query({ currentWindow: true, active: true }, tabs => {
if (!tabs || tabs.length === 0) return; if (!tabs || tabs.length === 0) return;
const [{ url }] = tabs; const [{ url }] = tabs;
@@ -190,8 +188,6 @@ function populateOptions(SECTIONS, headerSettings, SETTING_VALUES) {
const input = qs('input', LOCK_CODE_CONTAINER); const input = qs('input', LOCK_CODE_CONTAINER);
qs('div#code', LOCK_CODE_CONTAINER).innerText = code; qs('div#code', LOCK_CODE_CONTAINER).innerText = code;
input.addEventListener('input', e => { input.addEventListener('input', e => {
console.log(input.value);
console.log();
if (input.value === code) { if (input.value === code) {
HTML.removeAttribute('entering_lock_code', ''); HTML.removeAttribute('entering_lock_code', '');
} }
@@ -395,7 +391,12 @@ function timerLoop() {
// For timedChanged and scheduling // For timedChanged and scheduling
let timeLoopId = null;
function timeLoop() { function timeLoop() {
// Don't run if page is hidden
if (document.hidden) return;
const { const {
schedule, scheduleTimes, scheduleDays, schedule, scheduleTimes, scheduleDays,
nextTimedChange, nextTimedValue nextTimedChange, nextTimedValue
@@ -420,9 +421,23 @@ function timeLoop() {
} }
updateTimeInfo(); updateTimeInfo();
setTimeout(() => timeLoop(), 2_000); timeLoopId = setTimeout(() => timeLoop(), 2_000);
} }
// Pause/resume timeLoop based on visibility
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
if (timeLoopId) {
clearTimeout(timeLoopId);
timeLoopId = null;
}
} else {
if (!timeLoopId) {
timeLoop();
}
}
});
// Announcement banners // Announcement banners
function initAnnouncementBanner() { function initAnnouncementBanner() {
@@ -432,6 +447,7 @@ function initAnnouncementBanner() {
const logoUrl = browser.runtime.getURL('images/rys.svg'); const logoUrl = browser.runtime.getURL('images/rys.svg');
const banners = getActiveBanners('options'); const banners = getActiveBanners('options');
banners.forEach(banner => { banners.forEach(banner => {
initBanner(banner, logoUrl, () => ({ initBanner(banner, logoUrl, () => ({
element: container, element: container,
@@ -439,3 +455,28 @@ function initAnnouncementBanner() {
})); }));
}); });
} }
// Logging opt-in banner
function showLogPrompt() {
const banner = document.getElementById('log_prompt_banner');
const yesBtn = document.getElementById('log_prompt_yes');
const noBtn = document.getElementById('log_prompt_no');
const dismissBtn = document.getElementById('log_prompt_dismiss');
banner.hidden = false;
yesBtn.addEventListener('click', () => {
browser.storage.local.set({ log_enabled: true, log_prompt_answered: true });
banner.hidden = true;
}, { once: true });
noBtn.addEventListener('click', () => {
browser.storage.local.set({ log_enabled: false, log_prompt_answered: true });
banner.hidden = true;
}, { once: true });
dismissBtn.addEventListener('click', () => {
banner.hidden = true;
}, { once: true });
}
-1
View File
@@ -294,7 +294,6 @@ importSubmit.addEventListener('click', e => {
try { try {
const settingsObj = settingsStrToObj(settingsStr); const settingsObj = settingsStrToObj(settingsStr);
console.log(settingsObj);
browser.storage.local.set(settingsObj).then(x => { browser.storage.local.set(settingsObj).then(x => {
updateSettings(settingsObj); updateSettings(settingsObj);
+1 -1
View File
@@ -4,7 +4,7 @@ for(h=0;h<i.length;h++)g(a,i[h]);var j="set set_once union unset remove delete".
mixpanel.init('44d2dff3b4d141679640b297d31d5093'); mixpanel.init('44d2dff3b4d141679640b297d31d5093');
function recordEvent(name, props={}) { function recordEvent(name, props={}) {
const logEnabled = document.documentElement.getAttribute('log_enabled') || 'true'; const logEnabled = document.documentElement.getAttribute('log_enabled') || 'false';
if (logEnabled !== 'true') return; if (logEnabled !== 'true') return;
+3 -1
View File
@@ -611,7 +611,8 @@ const PASSWORD_SETTINGS = {
const OTHER_SETTINGS = { const OTHER_SETTINGS = {
global_enable: true, global_enable: true,
dark_mode: false, dark_mode: false,
log_enabled: true, log_enabled: false,
log_prompt_answered: false,
...TIMED_SETTINGS, ...TIMED_SETTINGS,
...SCHEDULE_SETTINGS, ...SCHEDULE_SETTINGS,
...PASSWORD_SETTINGS, ...PASSWORD_SETTINGS,
@@ -737,6 +738,7 @@ const idToShortId = {
"add_reveal_end_of_video": '89', "add_reveal_end_of_video": '89',
"add_reveal_button": '90', // deprecated; migrated to add_reveal_* settings "add_reveal_button": '90', // deprecated; migrated to add_reveal_* settings
"remove_sidebar_infinite_scroll": '91', "remove_sidebar_infinite_scroll": '91',
"log_prompt_answered": '92',
}; };
+11 -3
View File
@@ -3,6 +3,14 @@ function uniq(array) { return Array.from(new Set(array)) }
function qs(query, root=document) { return root.querySelector(query) } function qs(query, root=document) { return root.querySelector(query) }
function qsa(query, root=document) { return Array.from(root.querySelectorAll(query)) } function qsa(query, root=document) { return Array.from(root.querySelectorAll(query)) }
/* YouTube URL Regexes */
const resultsPageRegex = new RegExp('.*://.*youtube\\.com/results.*', 'i');
const homepageRegex = new RegExp('.*://(www|m)\\.youtube\\.com(/)?$', 'i');
const shortsRegex = new RegExp('.*://.*youtube\\.com/shorts.*', 'i');
const videoPageRegex = new RegExp('.*://(www|m)\\.youtube\\.com/watch\\?v=.*', 'i');
const channelRegex = new RegExp('.*://.*youtube\\.com/(@|channel)', 'i');
const subsRegex = new RegExp(/\/feed\/subscriptions$/, 'i');
/* Scheduling */ /* Scheduling */
function timeIsValid(times) { function timeIsValid(times) {
@@ -66,18 +74,18 @@ function nextScheduleChange(times, days) {
if (!times || !days) return; if (!times || !days) return;
const current = checkSchedule(times, days); const current = checkSchedule(times, days);
const SEC_IN_WEEK = 10_080; const MIN_IN_WEEK = 10_080;
let testDate = new Date(); let testDate = new Date();
testDate.setSeconds(0); testDate.setSeconds(0);
let next = checkSchedule(times, days, testDate); let next = checkSchedule(times, days, testDate);
let i = 0; let i = 0;
while (current === next && i < SEC_IN_WEEK) { while (current === next && i < MIN_IN_WEEK) {
i += 1; i += 1;
testDate = new Date(testDate.getTime() + 60_000); testDate = new Date(testDate.getTime() + 60_000);
next = checkSchedule(times, days, testDate); next = checkSchedule(times, days, testDate);
} }
if (i > SEC_IN_WEEK) return; if (i >= MIN_IN_WEEK) return;
return testDate; return testDate;
} }