Compare commits

..

No commits in common. "988b2d59f49328bf96aadee7a8f6c426c8175f4f" and "aaa04a43b5eaf14f8763390a2f6065c0ac87d8dc" have entirely different histories.

4 changed files with 56 additions and 134 deletions

View File

@ -18,7 +18,5 @@ module.exports = {
eqeqeq: ['error', 'always', { null: 'ignore' }], eqeqeq: ['error', 'always', { null: 'ignore' }],
curly: ['error', 'multi-line'], curly: ['error', 'multi-line'],
'no-var': 'error', 'no-var': 'error',
'no-func-assign': 'off',
'no-inner-declarations': 'off',
}, },
}; };

View File

@ -54,10 +54,7 @@ A green checkmark will appear next to the *Save* button if your connection is wo
- **Autostart**: Autostart and prioritize videos send from this extension. - **Autostart**: Autostart and prioritize videos send from this extension.
## Test this extension ## Test this extension
Before continuing loading the temporary extension here, make sure to deactivate/delete the main extension first. Use the correct manifest file for your browser. Either rename the browser specific file to `manifest.json` before loading the addon or symlink it to the correct location, e.g. `ln -s manifest-firefox.json manifest.json`.
Symlink/copy the correct manifest file for your browser to the expected location, e.g. `ln -s manifest-firefox.json manifest.json`.
- Firefox - Firefox
- Open `about:debugging#/runtime/this-firefox` - Open `about:debugging#/runtime/this-firefox`
- Click on *Load Temporary Add-on* - Click on *Load Temporary Add-on*

View File

@ -38,11 +38,6 @@ function clearError() {
errorOut.style.display = 'none'; errorOut.style.display = 'none';
} }
function clearTempLocalStorage() {
browserType.storage.local.remove('popupApiKey');
browserType.storage.local.remove('popupFullUrl');
}
// store access details // store access details
document.getElementById('save-login').addEventListener('click', function () { document.getElementById('save-login').addEventListener('click', function () {
let url = document.getElementById('full-url').value; let url = document.getElementById('full-url').value;
@ -83,21 +78,6 @@ document.getElementById('autostart').addEventListener('click', function () {
toggleAutostart(); toggleAutostart();
}); });
let fullUrlInput = document.getElementById('full-url');
fullUrlInput.addEventListener('change', () => {
browserType.storage.local.set({
popupFullUrl: fullUrlInput.value,
});
});
let apiKeyInput = document.getElementById('api-key');
apiKeyInput.addEventListener('change', () => {
browserType.storage.local.set({
popupApiKey: apiKeyInput.value,
});
});
function sendCookie() { function sendCookie() {
console.log('popup send cookie'); console.log('popup send cookie');
clearError(); clearError();
@ -144,7 +124,6 @@ function toggleAutostart() {
// send ping message to TA backend // send ping message to TA backend
function pingBackend() { function pingBackend() {
clearError(); clearError();
clearTempLocalStorage();
function handleResponse() { function handleResponse() {
console.log('connection validated'); console.log('connection validated');
setStatusIcon(true); setStatusIcon(true);
@ -200,18 +179,11 @@ function setStatusIcon(connected) {
} }
} }
// fill in form // fill in form
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
function onGot(item) { function onGot(item) {
if (!item.access) { if (!item.access) {
console.log('no access details found'); console.log('no access details found');
if (item.popupFullUrl != null && fullUrlInput.value === '') {
fullUrlInput.value = item.popupFullUrl;
}
if (item.popupApiKey != null && apiKeyInput.value === '') {
apiKeyInput.value = item.popupApiKey;
}
setStatusIcon(false); setStatusIcon(false);
return; return;
} }
@ -245,7 +217,7 @@ document.addEventListener('DOMContentLoaded', async () => {
document.getElementById('autostart').checked = true; document.getElementById('autostart').checked = true;
} }
browserType.storage.local.get(['access', 'popupFullUrl', 'popupApiKey'], function (result) { browserType.storage.local.get('access', function (result) {
onGot(result); onGot(result);
}); });

View File

@ -124,13 +124,13 @@ function isElementVisible(element) {
function ensureTALinks() { function ensureTALinks() {
let channelContainerNodes = getChannelContainers(); let channelContainerNodes = getChannelContainers();
for (let channelContainer of channelContainerNodes) { for (let channelContainer of channelContainerNodes) {
channelContainer = adjustOwner(channelContainer); channelContainer = adjustOwner(channelContainer);
if (channelContainer.hasTA) continue; if (channelContainer.hasTA) continue;
let channelButton = buildChannelButton(channelContainer);
channelContainer.appendChild(channelButton);
channelContainer.hasTA = true; channelContainer.hasTA = true;
buildChannelButton(channelContainer).then(channelButton => {
channelContainer.appendChild(channelButton);
});
} }
let titleContainerNodes = getTitleContainers(); let titleContainerNodes = getTitleContainers();
@ -143,69 +143,42 @@ function ensureTALinks() {
titleContainer.hasTA = true; titleContainer.hasTA = true;
} }
} }
ensureTALinks = throttled(ensureTALinks, 700);
// fix positioning of #owner div to fit new button
function adjustOwner(channelContainer) { function adjustOwner(channelContainer) {
return channelContainer.querySelector('#buttons') || channelContainer; return channelContainer.querySelector('#buttons') || channelContainer;
} }
function buildChannelButton(channelContainer) { function buildChannelButton(channelContainer) {
let channelHandle = getChannelHandle(channelContainer); return new Promise(resolve => {
channelContainer.taDerivedHandle = channelHandle; let buttonDiv;
let channelSubButton;
let spacer;
let channelDownloadButton;
let buttonDiv = buildChannelButtonDiv(); // Delayed execution for interface to refresh
setTimeout(() => {
let channelSubButton = buildChannelSubButton(channelHandle); const channelHandle = getChannelHandle(channelContainer);
buttonDiv.appendChild(channelSubButton); buttonDiv = buildChannelButtonDiv();
channelContainer.taSubButton = channelSubButton; channelSubButton = buildChannelSubButton(channelHandle);
spacer = buildSpacer();
let spacer = buildSpacer(); channelDownloadButton = buildChannelDownloadButton();
buttonDiv.appendChild(spacer); buttonDiv.appendChild(channelSubButton);
buttonDiv.appendChild(spacer);
let channelDownloadButton = buildChannelDownloadButton(); buttonDiv.appendChild(channelDownloadButton);
buttonDiv.appendChild(channelDownloadButton); resolve(buttonDiv);
channelContainer.taDownloadButton = channelDownloadButton; }, 2000);
});
if (!channelContainer.taObserver) {
function updateButtonsIfNecessary() {
let newHandle = getChannelHandle(channelContainer);
if (channelContainer.taDerivedHandle === newHandle) return;
console.log(`updating handle from ${channelContainer.taDerivedHandle} to ${newHandle}`);
channelContainer.taDerivedHandle = newHandle;
let channelSubButton = buildChannelSubButton(newHandle);
channelContainer.taSubButton.replaceWith(channelSubButton);
channelContainer.taSubButton = channelSubButton;
let channelDownloadButton = buildChannelDownloadButton();
channelContainer.taDownloadButton.replaceWith(channelDownloadButton);
channelContainer.taDownloadButton = channelDownloadButton;
}
channelContainer.taObserver = new MutationObserver(throttled(updateButtonsIfNecessary, 100));
channelContainer.taObserver.observe(channelContainer, {
attributes: true,
childList: true,
subtree: true,
});
}
return buttonDiv;
} }
function getChannelHandle(channelContainer) { function getChannelHandle(channelContainer) {
let channelHandle; const channelHandleContainer = document.querySelector('#channel-handle');
const videoOwnerRenderer = channelContainer.querySelector('.ytd-video-owner-renderer'); let channelHandle = channelHandleContainer ? channelHandleContainer.innerText : null;
if (!channelHandle) {
if (!videoOwnerRenderer) { let href = channelContainer.querySelector('.ytd-video-owner-renderer').href;
const channelHandleContainer = document.querySelector('#channel-handle'); const urlObj = new URL(href);
channelHandle = channelHandleContainer ? channelHandleContainer.innerText : null; channelHandle = urlObj.pathname.split('/')[1];
} else {
const href = videoOwnerRenderer.href;
if (href) {
const urlObj = new URL(href);
channelHandle = urlObj.pathname.split('/')[1];
}
} }
return channelHandle; return channelHandle;
} }
@ -263,10 +236,10 @@ function checkChannelSubscribed(channelSubButton) {
console.log('Unknown state'); console.log('Unknown state');
} }
} }
function handleError(e) { function handleError() {
buttonError(channelSubButton); buttonError(channelSubButton);
channelSubButton.innerText = 'Error'; channelSubButton.innerText = 'Error';
console.error('error', e); console.log('error');
} }
let channelHandle = channelSubButton.dataset.id; let channelHandle = channelSubButton.dataset.id;
@ -316,19 +289,16 @@ function buildChannelDownloadButton() {
} }
function getTitleContainers() { function getTitleContainers() {
let elements = document.querySelectorAll('#video-title'); let nodes = document.querySelectorAll('#video-title');
let videoNodes = []; return nodes;
elements.forEach(element => {
if (isElementVisible(element)) {
videoNodes.push(element);
}
});
return elements;
} }
function getVideoId(titleContainer) { function buildVideoButton(titleContainer) {
let href = getNearestLink(titleContainer); let href = getNearestLink(titleContainer);
if (!href) return; if (!href) return;
const dlButton = document.createElement('a');
dlButton.classList.add('ta-button');
dlButton.href = '#';
let videoId; let videoId;
if (href.startsWith('/watch?v')) { if (href.startsWith('/watch?v')) {
@ -337,16 +307,11 @@ function getVideoId(titleContainer) {
} else if (href.startsWith('/shorts/')) { } else if (href.startsWith('/shorts/')) {
videoId = href.split('/')[2]; videoId = href.split('/')[2];
} }
return videoId;
}
function buildVideoButton(titleContainer) {
let videoId = getVideoId(titleContainer);
if (!videoId) return; if (!videoId) return;
const dlButton = document.createElement('a'); dlButton.setAttribute('data-id', videoId);
dlButton.classList.add('ta-button'); dlButton.setAttribute('data-type', 'video');
dlButton.href = '#'; dlButton.title = `TA download video: ${titleContainer.innerText} [${videoId}]`;
Object.assign(dlButton.style, { Object.assign(dlButton.style, {
display: 'flex', display: 'flex',
@ -430,19 +395,13 @@ function checkVideoExists(taButton) {
} }
taButton.isChecked = true; taButton.isChecked = true;
} }
function handleError(e) { function handleError() {
buttonError(taButton); buttonError(taButton);
let videoId = taButton.dataset.id; let videoId = taButton.dataset.id;
console.log(`error: failed to get info from TA for video ${videoId}`); console.log(`error: failed to get info from TA for video ${videoId}`);
console.error(e);
} }
if (!taButton.parentElement) return; let videoId = taButton.dataset.id;
let videoId = getVideoId(taButton.parentElement);
taButton.setAttribute('data-id', videoId);
taButton.setAttribute('data-type', 'video');
taButton.title = `TA download video: ${taButton.parentElement.innerText} [${videoId}]`;
let message = { type: 'videoExists', videoId }; let message = { type: 'videoExists', videoId };
let sending = sendMessage(message); let sending = sendMessage(message);
sending.then(handleResponse, handleError); sending.then(handleResponse, handleError);
@ -496,8 +455,9 @@ function sendUrl(url, action, button) {
} }
} }
function handleError(e) { function handleError(error) {
console.log('error', e); console.log('error');
console.log(JSON.stringify(error));
buttonError(button); buttonError(button);
} }
@ -530,20 +490,15 @@ function cleanButtons() {
} }
let oldHref = document.location.href; let oldHref = document.location.href;
let throttleBlock;
function throttled(callback, time) { const throttle = (callback, time) => {
let throttleBlock = false; if (throttleBlock) return;
let lastArgs; throttleBlock = true;
return (...args) => { setTimeout(() => {
lastArgs = args; callback();
if (throttleBlock) return; throttleBlock = false;
throttleBlock = true; }, time);
setTimeout(() => { };
throttleBlock = false;
callback(...lastArgs);
}, time);
};
}
let observer = new MutationObserver(list => { let observer = new MutationObserver(list => {
const currentHref = document.location.href; const currentHref = document.location.href;
@ -552,7 +507,7 @@ let observer = new MutationObserver(list => {
oldHref = currentHref; oldHref = currentHref;
} }
if (list.some(i => i.type === 'childList' && i.addedNodes.length > 0)) { if (list.some(i => i.type === 'childList' && i.addedNodes.length > 0)) {
ensureTALinks(); throttle(ensureTALinks, 700);
} }
}); });