Add Preferences class to handle localStorage
This commit is contained in:
parent
bb34f11308
commit
02005a0ef8
|
@ -18,43 +18,43 @@ import * as _ from 'lodash/fp';
|
||||||
import * as browser from 'webextension-polyfill';
|
import * as browser from 'webextension-polyfill';
|
||||||
|
|
||||||
import { MessageKind } from './types';
|
import { MessageKind } from './types';
|
||||||
import { constants } from './constants';
|
import constants from './constants';
|
||||||
|
|
||||||
const buildSearchByNameURL = (instance: string, query: string): string => `https://${instance}/api/v1/search/videos?search=${encodeURIComponent(query)}`;
|
const buildSearchByNameURL = (instance: string, query: string): string => `https://${instance}/api/v1/search/videos?search=${encodeURIComponent(query)}`;
|
||||||
|
|
||||||
const searchByName = query => new Promise(async (resolve, reject) => {
|
const searchByName = query => new Promise(async (resolve, reject) => {
|
||||||
const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
|
const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
|
||||||
|
|
||||||
fetch(buildSearchByNameURL(instance, query))
|
fetch(buildSearchByNameURL(instance, query))
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
if (data.total > 0) {
|
if (data.total > 0) {
|
||||||
const video = data.data[0]
|
const video = data.data[0]
|
||||||
if (video.name === query) {
|
if (video.name === query) {
|
||||||
resolve(video);
|
resolve(video);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reject(new Error('No results.'));
|
reject(new Error('No results.'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildSearchByIDURL = (instance: string, id: string): string => `https://${instance}/api/v1/videos/${id}`;
|
const buildSearchByIDURL = (instance: string, id: string): string => `https://${instance}/api/v1/videos/${id}`;
|
||||||
|
|
||||||
const searchByID = id => new Promise(async (resolve, reject) => {
|
const searchByID = id => new Promise(async (resolve, reject) => {
|
||||||
const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
|
const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
|
||||||
|
|
||||||
fetch(buildSearchByIDURL(instance, id))
|
fetch(buildSearchByIDURL(instance, id))
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(function (video) {
|
.then(function(video) {
|
||||||
resolve({ url: `https://${instance}/videos/watch/${id}`, video });
|
resolve({ url: `https://${instance}/videos/watch/${id}`, video });
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener(function(message, sender) {
|
browser.runtime.onMessage.addListener(function(message, sender) {
|
||||||
switch (message.kind) {
|
switch (message.kind) {
|
||||||
case MessageKind.SearchByName:
|
case MessageKind.SearchByName:
|
||||||
return searchByName(message.query);
|
return searchByName(message.query);
|
||||||
case MessageKind.SearchByID:
|
case MessageKind.SearchByID:
|
||||||
return searchByID(message.id);
|
return searchByID(message.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export const constants = {
|
export default {
|
||||||
defaultInstance: 'peertube.social'
|
defaultInstance: 'peertube.social'
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
|
|
||||||
import * as _ from 'lodash/fp';
|
import * as _ from 'lodash/fp';
|
||||||
import * as browser from 'webextension-polyfill';
|
import * as browser from 'webextension-polyfill';
|
||||||
|
import Preferences from './preferences'
|
||||||
import { constants } from './constants';
|
|
||||||
|
|
||||||
function id(id: string): Element { return document.getElementById(id); }
|
function id(id: string): Element { return document.getElementById(id); }
|
||||||
|
|
||||||
|
@ -25,24 +24,18 @@ const searchInstance = () => id('search-instance') as HTMLInputElement;
|
||||||
const openInOriginalInstance = () => id('open-in-original-instance') as HTMLInputElement;
|
const openInOriginalInstance = () => id('open-in-original-instance') as HTMLInputElement;
|
||||||
const showOnPeertube = () => id('show-on-peertube') as HTMLInputElement;
|
const showOnPeertube = () => id('show-on-peertube') as HTMLInputElement;
|
||||||
|
|
||||||
function saveOptions(e) {
|
Preferences.getPreferences().then(preferences => {
|
||||||
e.preventDefault();
|
searchInstance().value = preferences.searchInstance;
|
||||||
browser.storage.local.set({
|
openInOriginalInstance().checked = preferences.openInOriginalInstance;
|
||||||
searchInstance: _.defaultTo(constants.defaultInstance, stripProtocol(searchInstance().value)),
|
showOnPeertube().checked = preferences.showOnPeertube;
|
||||||
openInOriginalInstance: _.defaultTo(true, openInOriginalInstance().checked),
|
|
||||||
showOnPeertube: _.defaultTo(false, showOnPeertube().checked),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const stripProtocol = _.replace(/^https?:\/\//, '');
|
function saveOptions(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
preferences.searchInstance = searchInstance().value;
|
||||||
|
preferences.openInOriginalInstance = openInOriginalInstance().checked;
|
||||||
|
preferences.showOnPeertube = showOnPeertube().checked;
|
||||||
|
preferences.save();
|
||||||
|
}
|
||||||
|
|
||||||
function restoreOptions() {
|
document.querySelector('form').addEventListener('submit', saveOptions);
|
||||||
browser.storage.local.get().then(result => {
|
})
|
||||||
searchInstance().value = _.defaultTo(constants.defaultInstance, result.searchInstance as string);
|
|
||||||
openInOriginalInstance().checked = _.defaultTo(true, result.openInOriginalInstance as boolean);
|
|
||||||
showOnPeertube().checked = _.defaultTo(false, result.showOnPeertube as boolean);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', restoreOptions);
|
|
||||||
document.querySelector('form').addEventListener('submit', saveOptions);
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import * as browser from 'webextension-polyfill';
|
||||||
|
|
||||||
import { htmlToElement } from './util';
|
import { htmlToElement } from './util';
|
||||||
import { MessageKind } from './types';
|
import { MessageKind } from './types';
|
||||||
import { constants } from './constants';
|
import Preferences from './preferences';
|
||||||
|
|
||||||
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
||||||
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||||
|
@ -27,37 +27,36 @@ const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||||
const LINK_ID = 'peertube-link';
|
const LINK_ID = 'peertube-link';
|
||||||
|
|
||||||
async function peertubeify() {
|
async function peertubeify() {
|
||||||
const options = await browser.storage.local.get();
|
const prefs = await Preferences.getPreferences()
|
||||||
const showOnPeertube = _.getOr(false, 'showOnPeertube', options);
|
|
||||||
const preferredInstance = _.getOr(constants.defaultInstance, 'searchInstance', options);
|
|
||||||
const isPreferredInstance = _.equals(preferredInstance, location.hostname)
|
|
||||||
if (showOnPeertube && !isPreferredInstance) {
|
|
||||||
const id = _.last(_.split('/', location.href));
|
|
||||||
|
|
||||||
browser.runtime.sendMessage({
|
const isPreferredInstance = _.equals(prefs.searchInstance, location.hostname)
|
||||||
kind: MessageKind.SearchByID,
|
if (prefs.showOnPeertube && !isPreferredInstance) {
|
||||||
id
|
const id = _.last(_.split('/', location.href));
|
||||||
}).then(async ({video, url}) => {
|
|
||||||
const link = videoLink(url, video);
|
|
||||||
|
|
||||||
removeVideoLink();
|
browser.runtime.sendMessage({
|
||||||
document.querySelector('body').appendChild(link);
|
kind: MessageKind.SearchByID,
|
||||||
}).catch(removeVideoLink);
|
id
|
||||||
}
|
}).then(async ({ video, url }) => {
|
||||||
|
const link = videoLink(url, video);
|
||||||
|
|
||||||
|
removeVideoLink();
|
||||||
|
document.querySelector('body').appendChild(link);
|
||||||
|
}).catch(removeVideoLink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const throttledPeertubeify = _.throttle(1000, peertubeify);
|
const throttledPeertubeify = _.throttle(1000, peertubeify);
|
||||||
const observer = new MutationObserver(function(mutationsList) {
|
const observer = new MutationObserver(function(mutationsList) {
|
||||||
for (const mutation of mutationsList) {
|
for (const mutation of mutationsList) {
|
||||||
if ((mutation.target as Element).id =='video-element-wrapper') {
|
if ((mutation.target as Element).id == 'video-element-wrapper') {
|
||||||
throttledPeertubeify();
|
throttledPeertubeify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
observer.observe(document.body, {
|
observer.observe(document.body, {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const videoLink = (url, video) => htmlToElement(`
|
const videoLink = (url, video) => htmlToElement(`
|
||||||
|
@ -114,6 +113,6 @@ const videoLink = (url, video) => htmlToElement(`
|
||||||
`);
|
`);
|
||||||
|
|
||||||
function removeVideoLink() {
|
function removeVideoLink() {
|
||||||
const existingLink = document.getElementById(LINK_ID);
|
const existingLink = document.getElementById(LINK_ID);
|
||||||
existingLink && existingLink.remove();
|
existingLink && existingLink.remove();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* 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 * as _ from 'lodash/fp';
|
||||||
|
import * as browser from 'webextension-polyfill';
|
||||||
|
import constants from './constants'
|
||||||
|
|
||||||
|
const stripProtocol = _.replace(/^https?:\/\//, '');
|
||||||
|
|
||||||
|
export default class Preferences {
|
||||||
|
private _searchInstance: string;
|
||||||
|
openInOriginalInstance: boolean;
|
||||||
|
showOnPeertube: boolean;
|
||||||
|
|
||||||
|
constructor(localStorage) {
|
||||||
|
this.searchInstance = _.defaultTo(constants.defaultInstance, localStorage.searchInstance as string);
|
||||||
|
this.openInOriginalInstance = _.defaultTo(true, localStorage.openInOriginalInstance as boolean);
|
||||||
|
this.showOnPeertube = _.defaultTo(false, localStorage.showOnPeertube as boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getPreferences() {
|
||||||
|
const localStorage = await browser.storage.local.get();
|
||||||
|
return new Preferences(localStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
async save() {
|
||||||
|
await browser.storage.local.set({
|
||||||
|
searchInstance: this.searchInstance,
|
||||||
|
openInOriginalInstance: this.openInOriginalInstance,
|
||||||
|
showOnPeertube: this.showOnPeertube,
|
||||||
|
})
|
||||||
|
const prefs = await browser.storage.local.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
get searchInstance() {
|
||||||
|
return this._searchInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
set searchInstance(instance) {
|
||||||
|
this._searchInstance = _.isEmpty(instance) ? constants.defaultInstance : stripProtocol(instance)
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ import * as browser from 'webextension-polyfill';
|
||||||
|
|
||||||
import { htmlToElement } from './util';
|
import { htmlToElement } from './util';
|
||||||
import { MessageKind } from './types';
|
import { MessageKind } from './types';
|
||||||
import { constants } from './constants';
|
import Preferences from './preferences'
|
||||||
|
|
||||||
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
|
||||||
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||||
|
@ -27,38 +27,36 @@ const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||||
const LINK_ID = 'peertube-link';
|
const LINK_ID = 'peertube-link';
|
||||||
|
|
||||||
function peertubeify(query: string) {
|
function peertubeify(query: string) {
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
kind: MessageKind.SearchByName,
|
kind: MessageKind.SearchByName,
|
||||||
query,
|
query,
|
||||||
}).then(async video => {
|
}).then(async video => {
|
||||||
const options = await browser.storage.local.get();
|
const prefs = await Preferences.getPreferences();
|
||||||
const openInOriginalInstance = _.getOr(true, 'openInOriginalInstance', options);
|
|
||||||
const searchInstance = _.getOr(constants.defaultInstance, 'searchInstance', options);
|
|
||||||
|
|
||||||
const url = watchURL(openInOriginalInstance ? video.account.host : searchInstance, video.uuid);
|
const url = watchURL(prefs.openInOriginalInstance ? video.account.host : prefs.searchInstance, video.uuid);
|
||||||
const link = videoLink(url, video);
|
const link = videoLink(url, video);
|
||||||
|
|
||||||
removeVideoLink();
|
removeVideoLink();
|
||||||
document.querySelector('ytd-app').appendChild(link);
|
document.querySelector('ytd-app').appendChild(link);
|
||||||
}).catch(removeVideoLink);
|
}).catch(removeVideoLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
const throttledPeertubify = _.throttle(1000, peertubeify);
|
const throttledPeertubify = _.throttle(1000, peertubeify);
|
||||||
const observer = new MutationObserver(function(mutationsList) {
|
const observer = new MutationObserver(function(mutationsList) {
|
||||||
for (const mutation of mutationsList) {
|
for (const mutation of mutationsList) {
|
||||||
if ((mutation.target as Element).classList.contains('ytp-title-link')) {
|
if ((mutation.target as Element).classList.contains('ytp-title-link')) {
|
||||||
for (const node of mutation.addedNodes) {
|
for (const node of mutation.addedNodes) {
|
||||||
if (node.nodeType == Node.TEXT_NODE) {
|
if (node.nodeType == Node.TEXT_NODE) {
|
||||||
throttledPeertubify(node.textContent);
|
throttledPeertubify(node.textContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
observer.observe(document.body, {
|
observer.observe(document.body, {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const videoLink = (url, video) => htmlToElement(`
|
const videoLink = (url, video) => htmlToElement(`
|
||||||
|
@ -119,6 +117,6 @@ const videoLink = (url, video) => htmlToElement(`
|
||||||
`);
|
`);
|
||||||
|
|
||||||
function removeVideoLink() {
|
function removeVideoLink() {
|
||||||
const existingLink = document.getElementById(LINK_ID);
|
const existingLink = document.getElementById(LINK_ID);
|
||||||
existingLink && existingLink.remove();
|
existingLink && existingLink.remove();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./built",
|
"outDir": "./built",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"node_modules/@types",
|
"node_modules/@types",
|
||||||
"node_modules/web-ext-types"
|
"node_modules/web-ext-types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./src/**/*"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"./src/**/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue