|
|
@@ -35,6 +35,7 @@ document.addEventListener("alpine:init", () => {
|
|
|
isCurrentTabYoutube: false, // Whether current tab is YouTube
|
|
|
isCurrentTabChannelPage: false, // Whether current tab is YouTube videos page
|
|
|
addCurrentPageButtonText: "Add Cur. Page", // Button text
|
|
|
+ scatterCount: 4,
|
|
|
|
|
|
// Save channel properties
|
|
|
selectedCategory: "FOR BOTH", // Currently selected category
|
|
|
@@ -693,6 +694,38 @@ document.addEventListener("alpine:init", () => {
|
|
|
return playlist.length;
|
|
|
},
|
|
|
|
|
|
+ async scatterLastN(playlistName, count) {
|
|
|
+ const playlists = JSON.parse(JSON.stringify(this.playlists));
|
|
|
+ const playlist = playlists[playlistName];
|
|
|
+ const n = playlist.length;
|
|
|
+ if (!playlist || count < 2 || count >= n) return;
|
|
|
+
|
|
|
+ const prefix = playlist.slice(0, n - count);
|
|
|
+ const tail = playlist.slice(n - count);
|
|
|
+ const insertions = [];
|
|
|
+ let cursor = prefix.length;
|
|
|
+
|
|
|
+ for (let i = count - 2; i >= 0; i--) {
|
|
|
+ const gap = Math.floor(Math.random() * 3) + 1;
|
|
|
+ cursor = Math.max(1, cursor - gap);
|
|
|
+ insertions.push([cursor, tail[i]]);
|
|
|
+ }
|
|
|
+ for (const [idx, video] of insertions) {
|
|
|
+ prefix.splice(idx, 0, video);
|
|
|
+ }
|
|
|
+ prefix.push(tail[count - 1]);
|
|
|
+
|
|
|
+ playlists[playlistName] = prefix;
|
|
|
+ try {
|
|
|
+ await browser.storage.local.set({ playlists });
|
|
|
+ this.playlists = playlists;
|
|
|
+ this.updatePlaylistsForDisplay();
|
|
|
+ this.updateCurrentPlaylistVideos();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error scattering videos:", error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
async toggleVideoDoneStatus(playlistName, index) {
|
|
|
const playlists = JSON.parse(JSON.stringify(this.playlists));
|
|
|
const playlist = [...playlists[playlistName]];
|
|
|
@@ -1463,6 +1496,32 @@ document.addEventListener("alpine:init", () => {
|
|
|
},
|
|
|
},
|
|
|
|
|
|
+ scatterCountInput: {
|
|
|
+ [":value"]() {
|
|
|
+ return this.scatterCount;
|
|
|
+ },
|
|
|
+ [":max"]() {
|
|
|
+ const pl = this.playlists[this.currentPlaylistName];
|
|
|
+ return pl ? pl.length - 1 : 2;
|
|
|
+ },
|
|
|
+ ["@input"]() {
|
|
|
+ const pl = this.playlists[this.currentPlaylistName];
|
|
|
+ const max = pl ? pl.length - 1 : 2;
|
|
|
+ const v = Math.min(max, Math.max(2, parseInt(this.$el.value) || 2));
|
|
|
+ this.scatterCount = v;
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ scatterButton: {
|
|
|
+ ["@click"]() {
|
|
|
+ this.scatterLastN(this.currentPlaylistName, this.scatterCount);
|
|
|
+ },
|
|
|
+ [":disabled"]() {
|
|
|
+ const pl = this.playlists[this.currentPlaylistName];
|
|
|
+ return !pl || this.scatterCount >= pl.length;
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
// Add current page button binding
|
|
|
addCurrentPageButton: {
|
|
|
["@click"]() {
|