I am building a chrome extension. The goal is to sort all open tabs from youtube by video duration (low to high).
I found this code from this GitHub project, explained in this tutorial:
popup.js
function byAlphabeticalURLOrder(tab1, tab2) {
if (tab1.url < tab2.url) {
return -1;
} else if (tab1.url > tab2.url) {
return 1;
}
return 0;
}
chrome.tabs.query({windowId: chrome.windows.WINDOW_ID_CURRENT}, (tabs) => {
tabs.sort(byAlphabeticalURLOrder);
for (let i = 0; i < tabs.length; i++) {
chrome.tabs.move(tabs[i].id, {index: i});
}
});
This code works perfectly with sorting by alphabetical order. However, I want to adjust it to sort by video duration.
So I wrote this file to get video duration from all open tabs but still can't get around to the "sorting or moving tabs" part.
popup.js
chrome.tabs.query({
windowId: chrome.windows.WINDOW_ID_CURRENT
}, (tabs) => {
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.executeScript(tabs[i].id, {
code: '(' + function () {
return {
seconds: document.querySelector("video").duration
};
} + ')()'
}, function (result) {
document.write(result[0].seconds + '<br>');
});
}
});
});
Output (Video duration in seconds) - (Appears in popup.html):
1229.041
187.501
510.581
609.941
1473.821
955.481
5464.281
59.201
1787.701
1523.941
It's not clear what you've tried, but you can add those values to objects in array in your existing loop and then sort that array in a second loop. Because executeScript is asynchronous, you need to wait for the first loop to finish, which means resolving a list of promises, then sorting the list on videolength, then moving the tabs.
Here's what I came up with for MV3. There are probably cleaner ways to do this (I'm fairly new at this):
*Edits: Minor edits to cleaned up code organization. Attached function to action (I.e., runs on clicking Chrome extension icon button).
popup.js
chrome.action.onClicked.addListener(sortTabsbyDuration);
async function sortTabsbyDuration() {
async function createListEntry(tabId, i) {
return new Promise((resolve) => {
if (/\.youtube\.com\/watch\?/.test(tabs[i].url)) {
chrome.scripting.executeScript(
{ target: { tabId: tabId }, func: getYouTubeLength, args: [tabId] },
(returnValue) => {
resolve(returnValue[0].result);
}
);
} else {
resolve({
tabId: tabId,
vidLength: 9999999999,
});
}
});
}
function getYouTubeLength(aTab) {
let vidLength = document.querySelector("video").duration;
if (!vidLength) {
vidLength=1;
}
return {
tabId: aTab,
vidLength: vidLength,
};
}
// MAIN:
const tabs = await chrome.tabs.query({ currentWindow: true });
let promiseList = [];
for (var index = 0; index < tabs.length; index++) {
promiseList.push(createListEntry(tabs[index].id, index));
}
const promisesFinished = Promise.all(promiseList);
const sortedList = (await promisesFinished).sort((a, b) => {
return a.vidLength - b.vidLength;
});
console.log(sortedList);
for (let index = 0; index < sortedList.length; index++) {
await chrome.tabs.move(sortedList[index].tabId, { index: index });
}
}
manifest.json
{
"manifest_version": 3,
"name": "Sort Your Tubes",
"version": "0.0.0.2",
"action": {
"default_title": "Click to sort YouTube videos by video length."
},
"background": {
"service_worker": "popup.js"
},
"permissions": [
"tabs",
"scripting"
],
"host_permissions": [
"*://www.youtube.com/*"
]
}