v0.2: use webpack, and DOM mutations to properly handle YT navigation
This commit is contained in:
parent
c54f8260fe
commit
7d97eb5885
|
@ -0,0 +1,2 @@
|
|||
extension/dist
|
||||
node_modules
|
|
@ -1,34 +0,0 @@
|
|||
/* This file is part of PeerTubeify.
|
||||
*
|
||||
* PeerTubeify is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PeerTubeify is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PeerTubeify. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function search(query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(`https://peertube.video/api/v1/videos/search?search=${encodeURIComponent(query)}`)
|
||||
.then(res => res.json())
|
||||
.then(function(data) {
|
||||
if (data.total > 0) {
|
||||
resolve(data.data[0]);
|
||||
} else {
|
||||
reject(new Error('No results.'))
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
browser.runtime.onMessage.addListener(function(message, sender) {
|
||||
return search(message.query)
|
||||
});
|
|
@ -1,19 +1,18 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "PeerTubeify",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "On YouTube, displays a link to the same video on PeerTube, if it exists.",
|
||||
"homepage_url": "https://gitlab.com/Ealhad/peertubeify",
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"notifications",
|
||||
"<all_urls>"
|
||||
],
|
||||
"background": {
|
||||
"scripts": ["background.js"]
|
||||
"scripts": ["dist/background.js"]
|
||||
},
|
||||
"content_scripts": [{
|
||||
"matches": ["*://*.youtube.com/watch*"],
|
||||
"js": ["youtube.js"]
|
||||
"matches": ["*://*.youtube.com/*"],
|
||||
"js": ["dist/youtube.js"]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "peertubeify",
|
||||
"version": "0.2.0",
|
||||
"description": "PeerTubeify is a browser extension to help discovering which YouTube videos are also available on PeerTube.",
|
||||
"main": "webpack.config.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"lodash": "^4.17.10",
|
||||
"webpack": "^4.16.5",
|
||||
"webpack-cli": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --display-error-details --progress --colors",
|
||||
"build:watch": "npm run build -- -w"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@gitlab.com/Ealhad/peertubeify.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/Ealhad/peertubeify/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/Ealhad/peertubeify#README"
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* This file is part of PeerTubeify.
|
||||
*
|
||||
* PeerTubeify is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* PeerTubeify is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* PeerTubeify. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const buildSearchURL = query => `https://peertube.video/api/v1/videos/search?search=${encodeURIComponent(query)}`;
|
||||
|
||||
function search(query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(buildSearchURL(query))
|
||||
.then(res => res.json())
|
||||
.then(function(data) {
|
||||
if (data.total > 0) {
|
||||
const video = data.data[0]
|
||||
resolve(video);
|
||||
} else {
|
||||
reject(new Error('No results.'))
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
browser.runtime.onMessage.addListener(function(message, sender) {
|
||||
return search(message.query)
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
/* This file is part of PeerTubeify.
|
||||
*
|
||||
* PeerTubeify is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* PeerTubeify is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* PeerTubeify. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
||||
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||
|
||||
const LINK_ID = 'peertube-link';
|
||||
|
||||
function peertubeify(query) {
|
||||
browser.runtime.sendMessage({
|
||||
query
|
||||
}).then(video => {
|
||||
removeVideoLink();
|
||||
const link = videoLink(video);
|
||||
document.querySelector('.title').insertAdjacentElement('afterend', link);
|
||||
});
|
||||
}
|
||||
|
||||
const throttledPeertubify = _.throttle(1000, peertubeify);
|
||||
const observer = new MutationObserver(function(mutationsList) {
|
||||
for (const mutation of mutationsList) {
|
||||
if (mutation.target.classList.contains('ytp-title-link')) {
|
||||
for (const node of mutation.addedNodes) {
|
||||
if (node.nodeType == Node.TEXT_NODE) {
|
||||
throttledPeertubify(node.textContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
})
|
||||
|
||||
function htmlToElement(html) {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = html.trim();
|
||||
return template.content.firstChild;
|
||||
}
|
||||
|
||||
function videoLink(video) {
|
||||
const url = watchURL(video.account.host, video.uuid);
|
||||
|
||||
return htmlToElement(`
|
||||
<a id="${LINK_ID}" style="display: flex; align-items: center; margin: 2rem 0;" href=${url}>
|
||||
<img src="${thumbnailURL(video.account.host, video.thumbnailPath)}">
|
||||
<p style="font-size: 18px; margin-left: 1rem; color: var(--ytd-video-primary-info-renderer-title-color, var(--yt-primary-text-color));">
|
||||
${video.account.host}
|
||||
</p>:
|
||||
</a>
|
||||
`);
|
||||
}
|
||||
|
||||
function removeVideoLink() {
|
||||
const existingLink = document.getElementById(LINK_ID);
|
||||
existingLink && existingLink.remove();
|
||||
}
|
||||
|
||||
function ready(fn) {
|
||||
if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
|
||||
fn();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', fn);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
background: 'background.js',
|
||||
youtube: 'youtube.js',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'extension', 'dist'),
|
||||
filename: '[name].js',
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to import modules just like you would in a NodeJS app.
|
||||
extensions: ['.js'],
|
||||
modules: [
|
||||
path.join(__dirname, 'src'),
|
||||
'node_modules',
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Since some NodeJS modules expect to be running in Node, it is helpful
|
||||
// to set this environment var to avoid reference errors.
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
}),
|
||||
],
|
||||
// This will expose source map files so that errors will point to your
|
||||
// original source files instead of the transpiled files.
|
||||
devtool: 'sourcemap',
|
||||
};
|
46
youtube.js
46
youtube.js
|
@ -1,46 +0,0 @@
|
|||
/* This file is part of PeerTubeify.
|
||||
*
|
||||
* PeerTubeify is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PeerTubeify is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PeerTubeify. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
||||
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||
|
||||
const title = document.title.slice(0, document.title.lastIndexOf(' -'));
|
||||
if (title) {
|
||||
browser.runtime.sendMessage({
|
||||
query: title,
|
||||
}).then(video => {
|
||||
document.querySelector('.title').insertAdjacentElement('afterend', videoLink(video));
|
||||
});
|
||||
}
|
||||
|
||||
function htmlToElement(html) {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = html.trim();
|
||||
return template.content.firstChild;
|
||||
}
|
||||
|
||||
function videoLink(video) {
|
||||
const url = watchURL(video.account.host, video.uuid);
|
||||
|
||||
return htmlToElement(`
|
||||
<a style="display: flex; align-items: center; margin: 2rem 0;" href=${url}>
|
||||
<img src="${thumbnailURL(video.account.host, video.thumbnailPath)}">
|
||||
<p style="font-size: 18px; margin-left: 1rem; color: var(--ytd-video-primary-info-renderer-title-color, var(--yt-primary-text-color));">
|
||||
${video.account.host}
|
||||
</p>:
|
||||
</a>
|
||||
`);
|
||||
}
|
Loading…
Reference in New Issue