Skip to content

Commit

Permalink
Display shorts sorting percentage on button (#293)
Browse files Browse the repository at this point in the history
  • Loading branch information
NikkelM authored May 26, 2024
1 parent 6f04bd1 commit e79e360
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 20 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Changelog

## v3.1.3-beta
## v3.1.3

<!--Releasenotes start-->
- When ignoring or only shuffling from shorts, the button will now more accurately display how long the shuffle will take.
- Cleaned up the popup and moved some settings to a separate menu.
- Fixed a bug where a correction of database corruption would reduce the user's daily API quota.
- Fixed a bug where fixing a rare database corruption issue would reduce the user's daily API quota.
<!--Releasenotes end-->

## v3.1.2
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "random-youtube-video",
"version": "3.1.2",
"version": "3.1.3",
"description": "Customize, shuffle and play random videos from any YouTube channel.",
"scripts": {
"dev": "concurrently \"npm run dev:chromium\" \"npm run dev:firefox\"",
Expand Down
3 changes: 1 addition & 2 deletions src/chromeStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ export async function getUserQuotaRemainingToday() {
return configSync.userQuotaRemainingToday;
}

// -- Private --
async function validateConfigSync() {
export async function validateConfigSync() {
const configSyncValues = await chrome.storage.sync.get();

// Set default values for config values that do not exist in sync storage
Expand Down
23 changes: 16 additions & 7 deletions src/shuffleVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ export async function chooseRandomVideo(channelId, firedFromPopup, progressTextE
try {
// While chooseRandomVideo is running, we need to keep the service worker alive
// Otherwise, it will get stopped after 30 seconds and we will get an error if fetching the videos takes longer
// So every 25 seconds, we send a message to the service worker to keep it alive
// So every 20 seconds, we send a message to the service worker to keep it alive
var keepServiceWorkerAlive = setInterval(() => {
chrome.runtime.sendMessage({ command: "connectionTest" });
}, 25000);
}, 20000);
/* c8 ignore stop */

// Each user has a set amount of quota they can use per day.
Expand Down Expand Up @@ -123,7 +123,7 @@ export async function chooseRandomVideo(channelId, firedFromPopup, progressTextE

let chosenVideos;
var encounteredDeletedVideos;
({ chosenVideos, playlistInfo, shouldUpdateDatabase, encounteredDeletedVideos } = await chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpdateDatabase));
({ chosenVideos, playlistInfo, shouldUpdateDatabase, encounteredDeletedVideos } = await chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpdateDatabase, progressTextElement));

// Save the playlist to the database and locally
playlistInfo = await handlePlaylistDatabaseUpload(playlistInfo, uploadsPlaylistId, shouldUpdateDatabase, databaseSharing, encounteredDeletedVideos);
Expand Down Expand Up @@ -674,7 +674,7 @@ async function isShort(videoId) {
return videoIsShort;
}

// Requests the API key from the background script
// Requests an API key from the background script
async function getAPIKey(useAPIKeyAtIndex = null) {
const msg = {
command: "getAPIKey",
Expand All @@ -701,7 +701,7 @@ async function getAPIKey(useAPIKeyAtIndex = null) {
return { APIKey, isCustomKey, keyIndex };
}

async function chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpdateDatabase) {
async function chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpdateDatabase, progressTextElement) {
let activeShuffleFilterOption = configSync.channelSettings[channelId]?.activeOption ?? "allVideosOption";
let activeOptionValue;

Expand Down Expand Up @@ -763,16 +763,21 @@ async function chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpd

console.log(`Choosing ${numVideosToChoose} random video(s).`);

// We keep track of the progress of determining the video types if there is a shorts handling filter, to display on the button
let numVideosProcessed = 0;
const initialTotalNumVideos = videosToShuffle.length;

// We use this label to break out of both the for loop and the while loop if there are no more videos after encountering a deleted video
outerLoop:
for (let i = 0; i < numVideosToChoose; i++) {
if (videosToShuffle.length === 0) {
// All available videos were chosen from, so we need to terminate the loop early
// All available videos were chosen, so we need to terminate the loop early
console.log(`No more videos to choose from (${numVideosToChoose - i} videos too few uploaded on channel).`);
break outerLoop;
}

randomVideo = videosToShuffle[Math.floor(Math.random() * videosToShuffle.length)];
numVideosProcessed++;

// If the video does not exist, remove it from the playlist and choose a new one, until we find one that exists
if (!await testVideoExistence(randomVideo, allVideos[randomVideo])) {
Expand All @@ -786,6 +791,7 @@ async function chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpd
// Remove the deleted video from the videosToShuffle array and choose a new random video
videosToShuffle.splice(videosToShuffle.indexOf(randomVideo), 1);
randomVideo = videosToShuffle[Math.floor(Math.random() * videosToShuffle.length)];
numVideosProcessed++;

console.log(`The chosen video does not exist anymore, so it will be removed from the database. A new random video has been chosen: ${randomVideo}`);

Expand Down Expand Up @@ -818,8 +824,11 @@ async function chooseRandomVideosFromPlaylist(playlistInfo, channelId, shouldUpd
if (playlistInfo["videos"]["unknownType"][randomVideo] !== undefined) {
const videoIsShort = await isShort(randomVideo);

// What follows is dependent on if the video is a short or not, and the user's settings
// We display either the percentage of videos processed or the percentage of videos chosen (vs. needed), whichever is higher
const percentage = Math.max(Math.round(chosenVideos.length / numVideosToChoose * 100), Math.round(numVideosProcessed / initialTotalNumVideos * 100));
updateProgressTextElement(progressTextElement, `\xa0Sorting: ${percentage}%`, `${percentage}%`);

// What follows is dependent on if the video is a short or not, and the user's settings
// Case 1: !isShort && ignoreShorts => Success
if (!videoIsShort && configSync.shuffleIgnoreShortsOption == "2") {
// Move the video to the knownVideos subdictionary
Expand Down
4 changes: 2 additions & 2 deletions static/manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "Random YouTube Video",
"description": "Customize, shuffle and play random videos from any YouTube channel.",
"version": "3.1.2",
"version_name": "3.1.3-beta",
"version": "3.1.3",
"version_name": "3.1.3",
"manifest_version": 3,
"content_scripts": [
{
Expand Down
68 changes: 64 additions & 4 deletions test/chromeStorage.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import expect from 'expect.js';

import { configSync, setSyncStorageValue, removeSyncStorageValue, getUserQuotaRemainingToday } from '../src/chromeStorage.js';
import { configSync, setSyncStorageValue, removeSyncStorageValue, getUserQuotaRemainingToday, validateConfigSync } from '../src/chromeStorage.js';
import { configSyncDefaults } from '../src/config.js';

describe('chromeStorage', function () {
Expand Down Expand Up @@ -75,7 +75,6 @@ describe('chromeStorage', function () {
});

context('removeSyncStorageValue()', function () {

it('should remove the value from the configSync object', async function () {
await setSyncStorageValue("testKey4", "testValue4");

Expand All @@ -86,10 +85,9 @@ describe('chromeStorage', function () {

expect(configSync).to.not.have.key("testKey4");
});

});
context('getUserQuotaRemainingToday()', function () {

context('getUserQuotaRemainingToday()', function () {
it('should return the number of requests the user can still make to the Youtube API today', async function () {
await setSyncStorageValue("userQuotaRemainingToday", 20);

Expand Down Expand Up @@ -117,7 +115,69 @@ describe('chromeStorage', function () {
// Check that the reset time is set to midnight
expect(configSync.userQuotaResetTime).to.be(new Date(new Date().setHours(24, 0, 0, 0)).getTime());
});
});

context('validateConfigSync()', function () {
context('fix incorrect settings', async function () {
it('should reset the useCustomApiKeyOption if no API key is set', async function () {
await setSyncStorageValue("useCustomApiKeyOption", true);
await setSyncStorageValue("customYoutubeApiKey", null);

await validateConfigSync();

expect(configSync.useCustomApiKeyOption).to.be(false);
});

it('should enable database sharing if no API key is set', async function () {
await setSyncStorageValue("useCustomApiKeyOption", false);
await setSyncStorageValue("databaseSharingEnabledOption", false);

await validateConfigSync();

expect(configSync.databaseSharingEnabledOption).to.be(true);
});

it('should disable reusing the new tab if shuffling does not open a new tab', async function () {
await setSyncStorageValue("shuffleOpenInNewTabOption", false);
await setSyncStorageValue("shuffleReUseNewTabOption", true);

await validateConfigSync();

expect(configSync.shuffleReUseNewTabOption).to.be(false);
});

it('should ensure valid values are set for ignoring shorts (0-2)', async function () {
// Too small
await setSyncStorageValue("shuffleIgnoreShortsOption", -1);

await validateConfigSync();

expect(configSync.shuffleIgnoreShortsOption).to.be(1);

// Too large
await setSyncStorageValue("shuffleIgnoreShortsOption", 3);

await validateConfigSync();

expect(configSync.shuffleIgnoreShortsOption).to.be(1);
});

it('should ensure valid values are set for the number of videos in a playlist', async function () {
// Too small
await setSyncStorageValue("shuffleNumVideosInPlaylist", 0);

await validateConfigSync();

expect(configSync.shuffleNumVideosInPlaylist).to.be(10);

// Too large
await setSyncStorageValue("shuffleNumVideosInPlaylist", 51);

await validateConfigSync();

expect(configSync.shuffleNumVideosInPlaylist).to.be(10);
});
});
});

});

0 comments on commit e79e360

Please sign in to comment.