Skip to content

Commit

Permalink
Added an option to reuse new tabs when shuffling again (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
NikkelM authored May 7, 2023
1 parent 49c1ffc commit 75e7ba0
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 30 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## v1.5.2

<!--Releasenotes start-->
- The default setting for shuffled videos was changed to open videos in a new tab. You can change this via the popup.
- Added logic to deal with a case where it was possible for the database to miss some videos.
- Added an option that allows you to reuse the same tab when shuffling multiple times from the same channel. This setting only takes effect if you have enabled the option to open shuffled videos in a new tab.
- Fixed a bug where it was possible for the database to not include some videos uploaded on a channel.
<!--Releasenotes end-->

## v1.5.1
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
alt="Chrome web store users"></a>
<br>
<a href="https://github.com/NikkelM/Random-YouTube-Video/tree/main/CHANGELOG.md">
<img src="https://img.shields.io/badge/View-changelog-lightgrey"
<img src="https://img.shields.io/badge/View-changelog-blue"
alt="View changelog"></a>
</p>

Expand All @@ -22,13 +22,15 @@ You can download the extension on the [Chrome Web Store](https://chrome.google.c

Do you have a favourite YouTube channel, but don't know what to watch? This extension is for you!

The Random YouTube Video extension adds a "Shuffle" button to YouTube channel and video pages, which will play a random video from the current channel. You can even choose what percentage of most recent videos should be considered when shuffling to exclude older videos!
The Random YouTube Video extension adds a "Shuffle" button to YouTube channel and video pages, which will play a random video from the current channel. You can use the extension's popup to customize your experience further.

Highlighted Features:<br>
- Sharing is caring: If another user has already shuffled from the channel you want to watch, the extension will run faster for you as video IDs are shared!
- Customize your experience: Choose from a wide range of options to individualize your experience, such as opening videos in a new tab or the channel's uploads playlist, and much more!
- Quick access: You don't need to open YouTube to shuffle from your favourite channels: The extension popup allows you to shuffle from your most recently visited channel at any time!
- Customize your experience: Choose from a wide range of options to individualize your experience, such as opening videos in a new tab, only shuffling from recent videos, and much more!
- Quick access: You don't need to open YouTube to shuffle from your favourite channels - the extension popup allows you to shuffle from your most recently visited channel at any time!

## Contribution

Do you have ideas for new features or encountered a bug? Please [open an issue](https://github.com/NikkelM/Random-YouTube-Video/issues/new/choose).
Do you have ideas for new features or have encountered a bug? Please [open an issue](https://github.com/NikkelM/Random-YouTube-Video/issues/new/choose).

If you enjoy this extension and want to say thanks, consider buying me a [coffee](https://ko-fi.com/nikkelm), or [sponsoring](https://github.com/sponsors/NikkelM) this project.
4 changes: 2 additions & 2 deletions extension/css/toggle.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.toggle label {
position: relative;
display: inline-block;
width: 9.3em;
width: 9em;
height: 3.5em;
}

Expand All @@ -19,7 +19,7 @@
position: absolute;
cursor: pointer;
top: 1.6em;
left: 3em;
left: 2.85em;
width: 3.5em;
height: 1.5em;
background-color: #c32e04;
Expand Down
23 changes: 17 additions & 6 deletions extension/html/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,28 @@ <h1>Random YouTube Video</h1>
<p class="grey-text">Hover over an option to view a more detailed explanation.</p>

<h3>General Video Settings</h3>
<!-- Shuffling: Open in new tab option toggle -->
<!-- First row of options -->
<div class="optionsRow">
<!-- Shuffling: Open in new tab option toggle -->
<div class="toggle optionsRow-item">
<label id="shuffleOpenInNewTabOption"
title="If this is enabled, shuffled videos will open in a new tab instead of the current one. This setting has no effect when using the shuffle button displayed in the popup, which will always open a new tab.">
title="If this is enabled, shuffled videos will open in a new tab instead of the current one. This setting is ignored when using the shuffle button displayed in the popup, which will always open a new tab.">
Open in new tab
<input type="checkbox" id="shuffleOpenInNewTabOptionToggle">
<span class="slider"></span>
</label>
</div>

<!-- Shuffling: Open in new tab option toggle -->
<div class="toggle optionsRow-item">
<label id="shuffleReUseNewTabOption"
title="If this is enabled, shuffling from a tab that was opened with a previous shuffle will not open yet another new tab, but reuse the current tab.">
Reuse new tab
<input type="checkbox" id="shuffleReUseNewTabOptionToggle">
<span class="slider"></span>
</label>
</div>

<!-- Shuffling: Open as playlist option toggle -->
<div class="toggle optionsRow-item">
<label id="shuffleOpenAsPlaylistOption"
Expand All @@ -40,6 +51,7 @@ <h3>General Video Settings</h3>
</label>
</div>
</div>
<!-- First row end -->

<!-- Settings for the most recently visited channel -->
<div id="channel">
Expand Down Expand Up @@ -128,10 +140,9 @@ <h3>API Settings</h3>

<!-- FYI -->
<div id="forYourInformationDiv">
<h2>For Your Information</h2>
<!-- Number of shuffled videos -->
<p id="numberOfShuffledVideosText" style="margin-bottom: 6px;">In total, you have shuffled 0
videos.</p>
<p id="numberOfShuffledVideosText" style="margin-bottom: 6px; margin-top: 6px;">You have shuffled 0 videos until
now.</p>
<!-- Daily quota notice -->
<div id="dailyQuotaNoticeDiv" class="hidden"
title="To protect the userbase against abuse, each user has a limited amount of requests to the YouTube API per day. This quota only ticks down if you are the first to shuffle from a channel, and should not effect users with normal usage patterns. If you are affected by this, you may make use of the custom API key option to remove this limitation.">
Expand All @@ -148,7 +159,7 @@ <h2>For Your Information</h2>
<a class="randomYoutubeVideoLink"
href="https://chrome.google.com/webstore/detail/random-youtube-video/kijgnjhogkjodpakfmhgleobifempckf"
target="_blank" rel="noopener">Chrome store</a>
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video/issues/new/choose"
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video/issues"
target="_blank" rel="noopener">Feedback</a>
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video" target="_blank"
rel="noopener">GitHub</a>
Expand Down
10 changes: 1 addition & 9 deletions extension/html/shufflingPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,14 @@ <h3 id="fetchPercentageNotice">Please wait...</h3>
<div id="shufflingInProgressElements">
<p><i>Closing this window will cancel the shuffle!</i></p>

<br>
<br>
<h3>Why is this taking so long?</h3>
<p class="grey-text">The extension needs to make a number of requests to the YouTube API to fetch the videos
uploaded on this channel.
<br>
Once this is done, a random video will automatically be played.
</p>
</div>

<br>
<footer id="randomYoutubeVideoFooter">
<a class="randomYoutubeVideoLink"
href="https://chrome.google.com/webstore/detail/random-youtube-video/kijgnjhogkjodpakfmhgleobifempckf"
target="_blank" rel="noopener">Chrome store</a>
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video/issues/new/choose"
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video/issues"
target="_blank" rel="noopener">Feedback</a>
<a class="randomYoutubeVideoLink" href="https://github.com/NikkelM/Random-YouTube-Video" target="_blank"
rel="noopener">GitHub</a>
Expand Down
16 changes: 14 additions & 2 deletions extension/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,12 @@ async function validateConfigSync() {
"customYoutubeApiKey": null,
// If the user has enabled sharing video ID's with the database
"databaseSharingEnabledOption": true,
// These two properties influence the behavior of the "shuffle" button
"shuffleOpenInNewTabOption": true,
// These properties influence the behavior of the "shuffle" button
"shuffleOpenInNewTabOption": false,
"shuffleOpenAsPlaylistOption": true,
"shuffleReUseNewTabOption": false,
// If shuffled videos are opened in a new tab, save the tab ID of that tab here to reuse the tab when the user shuffles again
"shuffleTabId": null,
// channelSettings is a dictionary of channelID -> Dictionary of channel settings
"channelSettings": {},
// These two properties are used by the popup to determine which channel's settings to show
Expand Down Expand Up @@ -193,6 +196,9 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
configSync = request.data;
sendResponse("New configSync set.");
break;
case "getCurrentTabId":
getCurrentTabId().then(sendResponse);
break;
default:
console.log(`Unknown command: ${request.command} (service worker). Hopefully another message listener will handle it.`);
sendResponse(`Unknown command: ${request.command} (service worker). Hopefully another message listener will handle it.`);
Expand Down Expand Up @@ -323,6 +329,12 @@ function rot13(message, encrypt) {
}
}

// Get the current tab ID. Content scripts cannot access the chrome.tabs API
async function getCurrentTabId() {
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
return tabs[0].id;
}

// ---------- Local storage ----------

async function getFromLocalStorage(key) {
Expand Down
16 changes: 15 additions & 1 deletion extension/js/popup/domElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ function getDomElements() {
dbSharingOptionToggle: document.getElementById("dbSharingOptionToggle"),
// Shuffling: Open in new tab option toggle
shuffleOpenInNewTabOptionToggle: document.getElementById("shuffleOpenInNewTabOptionToggle"),
// Shuffling: Reuse tab option toggle
shuffleReUseNewTabOptionToggle: document.getElementById("shuffleReUseNewTabOptionToggle"),
// Shuffling: Open as playlist option toggle
shuffleOpenAsPlaylistOptionToggle: document.getElementById("shuffleOpenAsPlaylistOptionToggle"),

Expand Down Expand Up @@ -77,6 +79,10 @@ async function setDomElementValuesFromConfig(domElements, configSync) {
// ----- Shuffling: Open in new tab option toggle -----
domElements.shuffleOpenInNewTabOptionToggle.checked = configSync.shuffleOpenInNewTabOption;

// ----- Shuffling: Reuse tab option toggle -----
// If this option is enabled depends on the state of the shuffleOpenInNewTabOptionToggle
manageDependents(domElements, domElements.shuffleOpenInNewTabOptionToggle, configSync.shuffleOpenInNewTabOption, configSync);

// ----- Shuffling: Open as playlist option toggle -----
domElements.shuffleOpenAsPlaylistOptionToggle.checked = configSync.shuffleOpenAsPlaylistOption;

Expand Down Expand Up @@ -138,6 +144,14 @@ async function setDomElemenEventListeners(domElements, configSync) {
manageDependents(domElements, domElements.shuffleOpenInNewTabOptionToggle, this.checked, configSync);
});

// Shuffling: Reuse tab option toggle
domElements.shuffleReUseNewTabOptionToggle.addEventListener("change", async function () {
configSync.shuffleReUseNewTabOption = this.checked;
await setSyncStorageValue("shuffleReUseNewTabOption", this.checked, configSync);

manageDependents(domElements, domElements.shuffleReUseNewTabOptionToggle, this.checked, configSync);
});

// Shuffling: Open as playlist option toggle
domElements.shuffleOpenAsPlaylistOptionToggle.addEventListener("change", async function () {
configSync.shuffleOpenAsPlaylistOption = this.checked;
Expand Down Expand Up @@ -278,7 +292,7 @@ async function updateFYIDiv(domElements, configSync) {
// ----- FYI: Number of shuffled videos text -----
// Use toLocaleString() to add commas/periods to large numbers
const numShuffledVideosTotal = configSync.numShuffledVideosTotal.toLocaleString();
domElements.numberOfShuffledVideosText.innerText = `In total, you have shuffled ${numShuffledVideosTotal} video${(configSync.numShuffledVideosTotal !== 1) ? "s" : ""}.`;
domElements.numberOfShuffledVideosText.innerText = `You have shuffled ${numShuffledVideosTotal} video${(configSync.numShuffledVideosTotal !== 1) ? "s" : ""} until now.`;

// ----- Daily quota notice -----
await getUserQuotaRemainingToday(configSync);
Expand Down
14 changes: 14 additions & 0 deletions extension/js/popup/popupUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ async function manageDependents(domElements, parent, value, configSync) {
// This is called after validation of a provided API key
// Depending on whether or not it is valid, we need to update the FYI div
updateFYIDiv(domElements, configSync);
break;
case domElements.shuffleOpenInNewTabOptionToggle:
// If it was turned off, we need to disable the reuse tab option toggle
if (value) {
// We call this function when first opening the popup, so this is where the initial state of the reuse tab option is set
domElements.shuffleReUseNewTabOptionToggle.checked = configSync.shuffleReUseNewTabOption;
domElements.shuffleReUseNewTabOptionToggle.parentElement.classList.remove("disabled");
} else {
// If the open in a new tab option gets disabled, we also want to disable the reuse tab option to avoid confusion
domElements.shuffleReUseNewTabOptionToggle.checked = false;
await setSyncStorageValue("shuffleReUseNewTabOption", false, configSync);
domElements.shuffleReUseNewTabOptionToggle.parentElement.classList.add("disabled");
}
break
default:
console.log(`No dependents to manage for element: ${parent.id}`);
break;
Expand Down
16 changes: 14 additions & 2 deletions extension/js/shuffleVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,15 +664,19 @@ function chooseVideoWithFilter(allVideos, videosByDate, activeShuffleFilterOptio
return videosToShuffle;
}

function playVideo(randomVideo, uploadsPlaylistId, firedFromPopup) {
async function playVideo(randomVideo, uploadsPlaylistId, firedFromPopup) {
// Get the correct URL format
let randomVideoURL = configSync.shuffleOpenAsPlaylistOption
? `https://www.youtube.com/watch?v=${randomVideo}&list=${uploadsPlaylistId}`
: `https://www.youtube.com/watch?v=${randomVideo}`;

// Get the current tab id
const currentTabId = await chrome.runtime.sendMessage({ command: "getCurrentTabId" });

// Open the video in a new tab or in the current tab, depending on the user's settings
// If the shuffle button from the popup was used, we always open the video in the same tab (==the shuffling page)
if (configSync.shuffleOpenInNewTabOption && !firedFromPopup) {
// If the user wants to reuse tabs, we only open in a new tab if the last shuffle did not open the current tab
if (configSync.shuffleOpenInNewTabOption && !firedFromPopup && (!configSync.shuffleReUseNewTabOption || currentTabId !== configSync.shuffleTabId)) {
// Video page: Pause the current video if it is playing
if (isVideoUrl(window.location.href)) {
const player = document.querySelector('ytd-player#ytd-player')?.children[0]?.children[0];
Expand All @@ -694,13 +698,21 @@ function playVideo(randomVideo, uploadsPlaylistId, firedFromPopup) {

window.open(randomVideoURL, '_blank').focus();

// Save the ID of the opened tab
await setSyncStorageValue("shuffleTabId", await chrome.runtime.sendMessage({ command: "getCurrentTabId" }));

// April fools joke: Users get rickrolled once on April 1st every year
// If we open both videos in a new tab, we want the rickroll to be focused
aprilFoolsJoke();
} else {
// Else, we need to open the rickroll first, as otherwise the function call doesn't happen
aprilFoolsJoke();

if (firedFromPopup) {
// Save the ID of the opened tab, as it is always a new tab when coming from the popup
await setSyncStorageValue("shuffleTabId", await chrome.runtime.sendMessage({ command: "getCurrentTabId" }));
}

window.location.href = randomVideoURL;
}
}
Expand Down
2 changes: 1 addition & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Random YouTube Video",
"description": "Play a random video uploaded on the current YouTube channel.",
"version": "1.5.1",
"version": "1.5.2",
"icons": {
"16": "images/icon-16-red.png",
"32": "images/icon-32-red.png",
Expand Down

0 comments on commit 75e7ba0

Please sign in to comment.