mirror of
https://github.com/lawrencehook/remove-youtube-suggestions.git
synced 2026-07-25 06:54:31 +00:00
Merge main into released
This commit is contained in:
@@ -2,3 +2,4 @@ keys/
|
||||
web-ext-artifacts/
|
||||
extension.zip
|
||||
manifest.json
|
||||
_scratch/
|
||||
|
||||
@@ -1,31 +1,17 @@
|
||||
# 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
|
||||
|
||||
- [ ] Auto-generate `idToShortId` map from `SECTIONS` instead of manual maintenance
|
||||
- [ ] Add storage validation/migration for schema changes between versions
|
||||
- [ ] Improve error handling beyond `console.log(error)`
|
||||
- [ ] Clean up event listeners in `options/main.js` to prevent memory leaks
|
||||
|
||||
## i18n / Localization
|
||||
|
||||
Hardcoded English strings that break for non-English YouTube:
|
||||
- `content-script/main.js:171` — `'for you'` comparison
|
||||
- `content-script/main.js:211` — `'Streamed'` check
|
||||
- `content-script/main.js:467-468` — `'All'`, `'Related'` chip names
|
||||
- `content-script/main.js` — `'for you'` comparison
|
||||
- `content-script/main.js` — `'Streamed'` check
|
||||
- `content-script/main.js` — `'All'`, `'Related'` chip names
|
||||
|
||||
## Incomplete Features
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.",
|
||||
"homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions",
|
||||
"manifest_version": 3,
|
||||
"version": "4.3.68",
|
||||
"version": "4.3.69",
|
||||
|
||||
"icons": {
|
||||
"16": "/images/16.png",
|
||||
|
||||
+55
-96
@@ -10,12 +10,6 @@ const REDIRECT_URLS = {
|
||||
"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
|
||||
const cache = {};
|
||||
@@ -49,7 +43,7 @@ let theaterClicked = false, hyper = false;
|
||||
let onResultsPage = resultsPageRegex.test(url);
|
||||
let onHomepage = homepageRegex.test(url);
|
||||
let onShorts = shortsRegex.test(url);
|
||||
let onVideo = videoRegex.test(url);
|
||||
let onVideo = videoPageRegex.test(url);
|
||||
let onChannel = channelRegex.test(url);
|
||||
let onSubs = subsRegex.test(url);
|
||||
let settingsInit = false
|
||||
@@ -57,8 +51,6 @@ let settingsInit = false
|
||||
let dynamicIters = 0;
|
||||
let frameRequested = false;
|
||||
let isRunning = false;
|
||||
// let lastRun = Date.now();
|
||||
// let counter = 0;
|
||||
let lastScheduleCheck;
|
||||
const scheduleInterval = 2_000; // 2 seconds
|
||||
let lastRedirect;
|
||||
@@ -113,8 +105,6 @@ document.addEventListener("DOMContentLoaded", e => handleNewPage());
|
||||
// Dynamic settings (i.e. js instead of css)
|
||||
function runDynamicSettings() {
|
||||
if (isRunning) return;
|
||||
// console.log('runDynamicSettings', Date.now() - lastRun);
|
||||
// lastRun = Date.now();
|
||||
isRunning = true;
|
||||
dynamicIters += 1;
|
||||
const on = cache['global_enable'] === true;
|
||||
@@ -204,8 +194,10 @@ function runDynamicSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
// Subscriptions page options
|
||||
if (onSubs) {
|
||||
// Subscriptions page options (only if any sub-page settings are enabled)
|
||||
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 upcomingBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="UPCOMING"]';
|
||||
const shortsBadgeSelector = 'ytd-thumbnail-overlay-time-status-renderer[overlay-style="SHORTS"]';
|
||||
@@ -273,13 +265,15 @@ function runDynamicSettings() {
|
||||
});
|
||||
}
|
||||
|
||||
// Click on "dismiss" buttons
|
||||
const dismissButtons = qsa('#dismiss-button');
|
||||
dismissButtons.forEach(dismissButton => {
|
||||
if (dismissButton && dismissButton.offsetParent) {
|
||||
dismissButton.click();
|
||||
}
|
||||
})
|
||||
// Click on "dismiss" buttons (only check occasionally, not every iteration)
|
||||
if (dynamicIters % 5 === 0) {
|
||||
const dismissButtons = qsa('#dismiss-button');
|
||||
dismissButtons.forEach(dismissButton => {
|
||||
if (dismissButton && dismissButton.offsetParent) {
|
||||
dismissButton.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Disable autoplay
|
||||
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
|
||||
if (cache['auto_skip_ads'] === true) {
|
||||
|
||||
@@ -361,10 +345,7 @@ function runDynamicSettings() {
|
||||
});
|
||||
|
||||
// Click on "Skip ad" button
|
||||
const skipButtons = qsa('.ytp-ad-skip-button').
|
||||
concat(qsa('.ytp-ad-skip-button-modern')).
|
||||
concat(qsa('.ytp-skip-ad-button')).
|
||||
concat(qsa(CSS.escape("button#skip-button:2")));
|
||||
const skipButtons = qsa('.ytp-ad-skip-button, .ytp-ad-skip-button-modern, .ytp-skip-ad-button, .ytp-skip-ad button');
|
||||
|
||||
const skippableAd = skipButtons?.some(button => button.offsetParent);
|
||||
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
|
||||
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"]');
|
||||
@@ -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
|
||||
if (cache['expand_description'] || cache['remove_comments']) {
|
||||
const expandButton = qsa('#description #expand.button');
|
||||
@@ -508,8 +461,8 @@ function runDynamicSettings() {
|
||||
});
|
||||
}
|
||||
|
||||
// Reveal suggestions boxes
|
||||
REVEAL_BOX_CONFIGS.forEach(({ containerSelector, boxId, message, showAction, revealSetting }) => {
|
||||
// Reveal suggestions boxes (only check on early iterations)
|
||||
if (dynamicIters <= 30) REVEAL_BOX_CONFIGS.forEach(({ containerSelector, boxId, message, showAction, revealSetting }) => {
|
||||
|
||||
if (closedRevealBoxes.has(boxId)) return;
|
||||
if (qs(`#${boxId}`)) return;
|
||||
@@ -561,9 +514,11 @@ function runDynamicSettings() {
|
||||
|
||||
// Video Player: hide the 'clip' button.
|
||||
// The path[d=...] selector selects scissor SVGs.
|
||||
qsa('path[d^="M8 7c0 .55-.45 1-1 1s-1-.45-1-1"]').
|
||||
map(path => path.closest('#menu button')).
|
||||
forEach(b => b.setAttribute('scissor_button', ''));
|
||||
if (cache['remove_clip_button']) {
|
||||
qsa('path[d^="M8 7c0 .55-.45 1-1 1s-1-.45-1-1"]').
|
||||
map(path => path.closest('#menu button')).
|
||||
forEach(b => b?.setAttribute('scissor_button', ''));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -577,11 +532,35 @@ function runDynamicSettings() {
|
||||
|
||||
function requestRunDynamicSettings() {
|
||||
if (frameRequested || isRunning) return;
|
||||
if (document.hidden) return; // Pause polling when tab is hidden
|
||||
frameRequested = true;
|
||||
// setTimeout(() => runDynamicSettings(), 50);
|
||||
setTimeout(() => runDynamicSettings(), Math.min(100, 50 + 10 * dynamicIters));
|
||||
// Start fast (100ms), slow down to 500ms after page settles
|
||||
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() {
|
||||
if (!onHomepage) return;
|
||||
@@ -612,13 +591,16 @@ function injectScripts() {
|
||||
script.type = "text/javascript";
|
||||
script.innerText = `
|
||||
(function() {
|
||||
let pm;
|
||||
let pm, intervalId;
|
||||
function f() {
|
||||
if (!pm) pm = document.querySelector('yt-playlist-manager');
|
||||
if (pm) pm.canAutoAdvance_ = false;
|
||||
if (pm) {
|
||||
pm.canAutoAdvance_ = false;
|
||||
if (intervalId) clearInterval(intervalId);
|
||||
}
|
||||
}
|
||||
f();
|
||||
setInterval(f, 100);
|
||||
intervalId = setInterval(f, 100);
|
||||
})()
|
||||
`;
|
||||
document.body?.appendChild(script);
|
||||
@@ -637,7 +619,7 @@ function handleNewPage() {
|
||||
onResultsPage = resultsPageRegex.test(url);
|
||||
onHomepage = homepageRegex.test(url);
|
||||
onShorts = shortsRegex.test(url);
|
||||
onVideo = videoRegex.test(url);
|
||||
onVideo = videoPageRegex.test(url);
|
||||
onChannel = channelRegex.test(url);
|
||||
onSubs = subsRegex.test(url);
|
||||
settingsInit = false;
|
||||
@@ -696,29 +678,6 @@ function handleNewPage() {
|
||||
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) {
|
||||
HTML.setAttribute(id, value);
|
||||
cache[id] = value;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Spend less time on YouTube. Customize YouTube's user interface to be less engaging.",
|
||||
"homepage_url": "https://github.com/lawrencehook/remove-youtube-suggestions",
|
||||
"manifest_version": 2,
|
||||
"version": "4.3.68",
|
||||
"version": "4.3.69",
|
||||
|
||||
"icons": {
|
||||
"16": "/images/16.png",
|
||||
|
||||
+70
-1
@@ -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 */
|
||||
#timer_container {
|
||||
position: fixed;
|
||||
@@ -439,7 +508,7 @@ html[foo=bar] {
|
||||
|
||||
#sidebar {
|
||||
height: calc(6px + var(--body-height));
|
||||
width: 140px;
|
||||
width: 160px;
|
||||
padding: 8px 6px;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<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 class="info-row">
|
||||
<span class="info-label">Browser</span>
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
html[dark_mode='false'] { --svg-color: #464646 }
|
||||
html[dark_mode='true'] { --svg-color: #E9E9E9 }
|
||||
|
||||
#header-settings circle,
|
||||
#header-toggle path,
|
||||
.dark_mode circle, .dark_mode path
|
||||
{
|
||||
fill: var(--svg-color);
|
||||
}
|
||||
|
||||
#header-settings path,
|
||||
#header-settings circle {
|
||||
stroke: var(--svg-color);
|
||||
}
|
||||
|
||||
/* Dark mode styling */
|
||||
html[dark_mode='true'] #header-dark { display: none }
|
||||
html[dark_mode='false'] #header-light { display: none }
|
||||
@@ -169,9 +173,9 @@ html[foo=bar]
|
||||
}
|
||||
#header-settings {
|
||||
cursor: pointer;
|
||||
height: var(--icon-dim);
|
||||
max-height: var(--icon-dim);
|
||||
max-width: var(--icon-dim);
|
||||
height: calc(var(--icon-dim) - 6px);
|
||||
max-height: calc(var(--icon-dim) - 6px);
|
||||
max-width: calc(var(--icon-dim) - 6px);
|
||||
}
|
||||
#settings-menu {
|
||||
font-size: 14px;
|
||||
|
||||
+14
-6
@@ -121,6 +121,15 @@
|
||||
|
||||
</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>Menu Timer</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://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>
|
||||
<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-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-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="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>
|
||||
<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>
|
||||
@@ -203,10 +212,9 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<svg id='header-settings' viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" fill="black">
|
||||
<circle cx="12" cy="32" r="7"/>
|
||||
<circle cx="52" cy="32" r="7"/>
|
||||
<circle cx="32" cy="32" r="7"/>
|
||||
<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="12" r="3"/>
|
||||
<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"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
|
||||
+51
-10
@@ -5,7 +5,6 @@ const HTML = document.documentElement;
|
||||
const SIDEBAR = document.getElementById('sidebar');
|
||||
const TEMPLATE_SIDEBAR_SECTION = document.getElementById('template_sidebar_section');
|
||||
const OPTIONS_LIST = document.getElementById('primary_options');
|
||||
const TEMPLATE_FIELDSET = document.getElementById('template_fieldset');
|
||||
const TEMPLATE_SECTION = document.getElementById('template_section');
|
||||
const TEMPLATE_OPTION = document.getElementById('template_option');
|
||||
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 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", () => {
|
||||
recordEvent('Page View: Options');
|
||||
@@ -35,6 +28,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
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 => {
|
||||
if (!tabs || tabs.length === 0) return;
|
||||
const [{ url }] = tabs;
|
||||
@@ -190,8 +188,6 @@ function populateOptions(SECTIONS, headerSettings, SETTING_VALUES) {
|
||||
const input = qs('input', LOCK_CODE_CONTAINER);
|
||||
qs('div#code', LOCK_CODE_CONTAINER).innerText = code;
|
||||
input.addEventListener('input', e => {
|
||||
console.log(input.value);
|
||||
console.log();
|
||||
if (input.value === code) {
|
||||
HTML.removeAttribute('entering_lock_code', '');
|
||||
}
|
||||
@@ -395,7 +391,12 @@ function timerLoop() {
|
||||
|
||||
|
||||
// For timedChanged and scheduling
|
||||
let timeLoopId = null;
|
||||
|
||||
function timeLoop() {
|
||||
// Don't run if page is hidden
|
||||
if (document.hidden) return;
|
||||
|
||||
const {
|
||||
schedule, scheduleTimes, scheduleDays,
|
||||
nextTimedChange, nextTimedValue
|
||||
@@ -420,9 +421,23 @@ function timeLoop() {
|
||||
}
|
||||
|
||||
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
|
||||
function initAnnouncementBanner() {
|
||||
@@ -432,6 +447,7 @@ function initAnnouncementBanner() {
|
||||
const logoUrl = browser.runtime.getURL('images/rys.svg');
|
||||
const banners = getActiveBanners('options');
|
||||
|
||||
|
||||
banners.forEach(banner => {
|
||||
initBanner(banner, logoUrl, () => ({
|
||||
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 });
|
||||
}
|
||||
|
||||
@@ -294,7 +294,6 @@ importSubmit.addEventListener('click', e => {
|
||||
|
||||
try {
|
||||
const settingsObj = settingsStrToObj(settingsStr);
|
||||
console.log(settingsObj);
|
||||
|
||||
browser.storage.local.set(settingsObj).then(x => {
|
||||
updateSettings(settingsObj);
|
||||
|
||||
@@ -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');
|
||||
|
||||
function recordEvent(name, props={}) {
|
||||
const logEnabled = document.documentElement.getAttribute('log_enabled') || 'true';
|
||||
const logEnabled = document.documentElement.getAttribute('log_enabled') || 'false';
|
||||
|
||||
if (logEnabled !== 'true') return;
|
||||
|
||||
|
||||
+3
-1
@@ -611,7 +611,8 @@ const PASSWORD_SETTINGS = {
|
||||
const OTHER_SETTINGS = {
|
||||
global_enable: true,
|
||||
dark_mode: false,
|
||||
log_enabled: true,
|
||||
log_enabled: false,
|
||||
log_prompt_answered: false,
|
||||
...TIMED_SETTINGS,
|
||||
...SCHEDULE_SETTINGS,
|
||||
...PASSWORD_SETTINGS,
|
||||
@@ -737,6 +738,7 @@ const idToShortId = {
|
||||
"add_reveal_end_of_video": '89',
|
||||
"add_reveal_button": '90', // deprecated; migrated to add_reveal_* settings
|
||||
"remove_sidebar_infinite_scroll": '91',
|
||||
"log_prompt_answered": '92',
|
||||
};
|
||||
|
||||
|
||||
|
||||
+11
-3
@@ -3,6 +3,14 @@ function uniq(array) { return Array.from(new Set(array)) }
|
||||
function qs(query, root=document) { return root.querySelector(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 */
|
||||
function timeIsValid(times) {
|
||||
@@ -66,18 +74,18 @@ function nextScheduleChange(times, days) {
|
||||
if (!times || !days) return;
|
||||
|
||||
const current = checkSchedule(times, days);
|
||||
const SEC_IN_WEEK = 10_080;
|
||||
const MIN_IN_WEEK = 10_080;
|
||||
let testDate = new Date();
|
||||
testDate.setSeconds(0);
|
||||
let next = checkSchedule(times, days, testDate);
|
||||
let i = 0;
|
||||
while (current === next && i < SEC_IN_WEEK) {
|
||||
while (current === next && i < MIN_IN_WEEK) {
|
||||
i += 1;
|
||||
testDate = new Date(testDate.getTime() + 60_000);
|
||||
next = checkSchedule(times, days, testDate);
|
||||
}
|
||||
|
||||
if (i > SEC_IN_WEEK) return;
|
||||
if (i >= MIN_IN_WEEK) return;
|
||||
|
||||
return testDate;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user