Add option to resume video through multiple instances
Closes #3 See merge request Ealhad/peertubeify!4
This commit is contained in:
commit
8aa3910352
|
@ -15,6 +15,22 @@
|
|||
<input style="flex-grow: 1" type="text" id="search-instance">
|
||||
</label>
|
||||
|
||||
<section>
|
||||
<label style="display: flex; align-items: center;">
|
||||
<p style="margin-right: 1rem">
|
||||
Open videos in original instance?
|
||||
</p>
|
||||
<input type="checkbox" id="open-in-original-instance">
|
||||
</label>
|
||||
|
||||
<label style="display: flex; align-items: center;">
|
||||
<p style="margin-right: 1rem">
|
||||
Automatically resume videos?
|
||||
</p>
|
||||
<input type="checkbox" id="resume-uncompleted-videos">
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>
|
||||
YouTube
|
||||
|
@ -36,13 +52,6 @@
|
|||
Redirect
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label style="margin-bottom: 1rem; display: flex; align-items: center;">
|
||||
<p style="margin-right: 1rem">
|
||||
Open videos in original instance?
|
||||
</p>
|
||||
<input type="checkbox" id="open-in-original-instance">
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -23,6 +23,7 @@ function id(id: string): Element { return document.getElementById(id); }
|
|||
|
||||
const searchInstance = () => id('search-instance') as HTMLInputElement;
|
||||
const openInOriginalInstance = () => id('open-in-original-instance') as HTMLInputElement;
|
||||
const resumeUncompletedVideo = () => id('resume-uncompleted-videos') as HTMLInputElement;
|
||||
|
||||
const checked = name => (document.querySelector(`input[name="${name}"]:checked`) as HTMLInputElement).value;
|
||||
const check = name => value => (document.querySelector(`input[name="${name}"][value="${value}"]`) as HTMLInputElement).checked = true
|
||||
|
@ -30,6 +31,7 @@ const check = name => value => (document.querySelector(`input[name="${name}"][va
|
|||
Preferences.getPreferences().then(prefs => {
|
||||
searchInstance().value = prefs.searchInstance;
|
||||
openInOriginalInstance().checked = prefs.openInOriginalInstance;
|
||||
resumeUncompletedVideo().checked = prefs.resumeUncompletedVideo;
|
||||
check('redirectPeertube')(prefs.redirectPeertube)
|
||||
check('redirectYoutube')(prefs.redirectYoutube)
|
||||
|
||||
|
@ -37,8 +39,9 @@ Preferences.getPreferences().then(prefs => {
|
|||
e.preventDefault();
|
||||
prefs.searchInstance = searchInstance().value;
|
||||
prefs.openInOriginalInstance = openInOriginalInstance().checked;
|
||||
prefs.redirectPeertube = checked('redirectPeertube') as RedirectType
|
||||
prefs.redirectYoutube = checked('redirectYoutube') as RedirectType
|
||||
prefs.resumeUncompletedVideo = resumeUncompletedVideo().checked;
|
||||
prefs.redirectPeertube = checked('redirectPeertube') as RedirectType;
|
||||
prefs.redirectYoutube = checked('redirectYoutube') as RedirectType;
|
||||
prefs.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import * as browser from 'webextension-polyfill';
|
|||
|
||||
import { htmlToElement, getPeertubeVideoURL } from './util';
|
||||
import { MessageKind, RedirectType } from './types';
|
||||
import { runResume } from './resume';
|
||||
import Preferences from './preferences';
|
||||
|
||||
const thumbnailURL = (host, path) => `https://${host}${path}`;
|
||||
|
@ -64,9 +65,11 @@ const observer = new MutationObserver(function(mutationsList) {
|
|||
for (const mutation of mutationsList) {
|
||||
if ((mutation.target as Element).id == 'video-element-wrapper') {
|
||||
throttledPeertubeify();
|
||||
runResume();
|
||||
}
|
||||
}
|
||||
});
|
||||
runResume();
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
|
|
|
@ -24,14 +24,16 @@ const stripProtocol = _.replace(/^https?:\/\//, '');
|
|||
export default class Preferences {
|
||||
private _searchInstance: string;
|
||||
openInOriginalInstance: boolean;
|
||||
resumeUncompletedVideo: boolean;
|
||||
redirectYoutube: RedirectType;
|
||||
redirectPeertube: RedirectType;
|
||||
|
||||
constructor(localStorage) {
|
||||
this.searchInstance = _.defaultTo(constants.peertubeAPI.defaultInstance, localStorage.searchInstance as string);
|
||||
this.openInOriginalInstance = _.defaultTo(true, localStorage.openInOriginalInstance as boolean);
|
||||
this.redirectYoutube = _.defaultTo(RedirectType.Show, localStorage.redirectYoutube)
|
||||
this.redirectPeertube = _.defaultTo(RedirectType.None, localStorage.redirectPeertube)
|
||||
this.resumeUncompletedVideo = _.defaultTo(true, localStorage.resumeUncompletedVideo as boolean);
|
||||
this.redirectYoutube = _.defaultTo(RedirectType.Show, localStorage.redirectYoutube);
|
||||
this.redirectPeertube = _.defaultTo(RedirectType.None, localStorage.redirectPeertube);
|
||||
}
|
||||
|
||||
static async getPreferences() {
|
||||
|
@ -43,6 +45,7 @@ export default class Preferences {
|
|||
await browser.storage.local.set({
|
||||
searchInstance: this.searchInstance,
|
||||
openInOriginalInstance: this.openInOriginalInstance,
|
||||
resumeUncompletedVideo: this.resumeUncompletedVideo,
|
||||
redirectYoutube: this.redirectYoutube,
|
||||
redirectPeertube: this.redirectPeertube,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import * as _ from 'lodash/fp';
|
||||
import * as browser from 'webextension-polyfill';
|
||||
import Preferences from './preferences';
|
||||
|
||||
interface VideoEntry {
|
||||
readonly uuid: string,
|
||||
currentTime: number,
|
||||
}
|
||||
|
||||
export async function runResume() {
|
||||
const prefs = await Preferences.getPreferences();
|
||||
|
||||
if (prefs.resumeUncompletedVideo) {
|
||||
const videoElement = document.getElementById('vjs_video_3_html5_api') as HTMLVideoElement;
|
||||
resumeVideo(videoElement);
|
||||
window.setInterval(() => updateStorage(videoElement), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
async function resumeVideo(videoElement: HTMLVideoElement) {
|
||||
const storage = await browser.storage.local.get('uncompletedVideos');
|
||||
const uncompletedVideos: Array<VideoEntry> = storage.uncompletedVideos;
|
||||
const uuid = _.last(_.split('/', location.href));
|
||||
|
||||
const savedEntry = _.find((e: VideoEntry) => e.uuid == uuid, uncompletedVideos);
|
||||
|
||||
if (savedEntry) {
|
||||
videoElement.currentTime = savedEntry.currentTime;
|
||||
browser.storage.local.set({ uncompletedVideos });
|
||||
}
|
||||
}
|
||||
|
||||
async function updateStorage(videoElement: HTMLVideoElement) {
|
||||
const storage = await browser.storage.local.get('uncompletedVideos');
|
||||
const uuid = _.last(_.split('/', location.href));
|
||||
|
||||
const uncompletedVideos: Array<VideoEntry> = storage.uncompletedVideos || [];
|
||||
|
||||
if (!videoElement.ended) {
|
||||
const entry: VideoEntry = {
|
||||
uuid,
|
||||
currentTime: videoElement.currentTime
|
||||
};
|
||||
|
||||
const savedEntry = _.find((e: VideoEntry) => e.uuid == uuid, uncompletedVideos);
|
||||
|
||||
if (savedEntry) {
|
||||
savedEntry.currentTime = entry.currentTime;
|
||||
} else {
|
||||
uncompletedVideos.push(entry);
|
||||
}
|
||||
} else {
|
||||
uncompletedVideos.splice(_.findIndex((e: VideoEntry) => e.uuid == uuid, uncompletedVideos), 1);
|
||||
}
|
||||
|
||||
browser.storage.local.set({ uncompletedVideos });
|
||||
};
|
Loading…
Reference in New Issue