Add Preferences class to handle localStorage

This commit is contained in:
Ealhad 2018-11-09 12:44:07 +01:00
parent bb34f11308
commit 02005a0ef8
7 changed files with 151 additions and 106 deletions

View File

@ -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);
} }
}); });

View File

@ -1,3 +1,3 @@
export const constants = { export default {
defaultInstance: 'peertube.social' defaultInstance: 'peertube.social'
}; };

View File

@ -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);

View File

@ -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();
} }

55
src/preferences.ts Normal file
View File

@ -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)
}
}

View File

@ -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();
} }

View File

@ -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/**/*"
]
} }