mirror of
https://github.com/SoPat712/videospeed.git
synced 2025-08-21 18:08:46 -04:00
93
inject.js
93
inject.js
@@ -18,7 +18,12 @@ var tc = {
|
|||||||
vine.co
|
vine.co
|
||||||
imgur.com
|
imgur.com
|
||||||
teams.microsoft.com
|
teams.microsoft.com
|
||||||
`.replace(regStrip, "")
|
`.replace(regStrip, ""),
|
||||||
|
blacklistrc: `\
|
||||||
|
twitch.tv
|
||||||
|
pluralsight.com
|
||||||
|
teamtreehouse.com
|
||||||
|
`.replace(regStrip, "")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +85,8 @@ chrome.storage.sync.get(tc.settings, function(storage) {
|
|||||||
startHidden: tc.settings.startHidden,
|
startHidden: tc.settings.startHidden,
|
||||||
enabled: tc.settings.enabled,
|
enabled: tc.settings.enabled,
|
||||||
controllerOpacity: tc.settings.controllerOpacity,
|
controllerOpacity: tc.settings.controllerOpacity,
|
||||||
blacklist: tc.settings.blacklist.replace(regStrip, "")
|
blacklist: tc.settings.blacklist.replace(regStrip, ""),
|
||||||
|
blacklistrc: tc.settings.blacklistrc.replace(regStrip, "")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
tc.settings.lastSpeed = Number(storage.lastSpeed);
|
tc.settings.lastSpeed = Number(storage.lastSpeed);
|
||||||
@@ -91,6 +97,7 @@ chrome.storage.sync.get(tc.settings, function(storage) {
|
|||||||
tc.settings.startHidden = Boolean(storage.startHidden);
|
tc.settings.startHidden = Boolean(storage.startHidden);
|
||||||
tc.settings.controllerOpacity = Number(storage.controllerOpacity);
|
tc.settings.controllerOpacity = Number(storage.controllerOpacity);
|
||||||
tc.settings.blacklist = String(storage.blacklist);
|
tc.settings.blacklist = String(storage.blacklist);
|
||||||
|
tc.settings.blacklistrc = String(storage.blacklistrc);
|
||||||
|
|
||||||
// ensure that there is a "display" binding (for upgrades from versions that had it as a separate binding)
|
// ensure that there is a "display" binding (for upgrades from versions that had it as a separate binding)
|
||||||
if (tc.settings.keyBindings.filter(x => x.action == "display").length == 0) {
|
if (tc.settings.keyBindings.filter(x => x.action == "display").length == 0) {
|
||||||
@@ -306,13 +313,13 @@ function defineVideoController() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeWhenReady(document) {
|
function escapeStringRegExp(str) {
|
||||||
escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
||||||
function escapeStringRegExp(str) {
|
return str.replace(matchOperatorsRe, "\\$&");
|
||||||
return str.replace(escapeStringRegExp.matchOperatorsRe, "\\$&");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var blacklisted = false;
|
function isBlacklisted() {
|
||||||
|
blacklisted = false;
|
||||||
tc.settings.blacklist.split("\n").forEach(match => {
|
tc.settings.blacklist.split("\n").forEach(match => {
|
||||||
match = match.replace(regStrip, "");
|
match = match.replace(regStrip, "");
|
||||||
if (match.length == 0) {
|
if (match.length == 0) {
|
||||||
@@ -334,9 +341,46 @@ function initializeWhenReady(document) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return blacklisted;
|
||||||
|
}
|
||||||
|
|
||||||
if (blacklisted) return;
|
function isRateChangeBlocked() {
|
||||||
|
blockRateChange = false;
|
||||||
|
tc.settings.blacklistrc.split("\n").forEach(match => {
|
||||||
|
match = match.replace(regStrip, "");
|
||||||
|
if (match.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (match.startsWith("/")) {
|
||||||
|
try {
|
||||||
|
var regexp = new RegExp(match);
|
||||||
|
} catch (err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var regexp = new RegExp(escapeStringRegExp(match));
|
||||||
|
}
|
||||||
|
if (regexp.test(location.href)) {
|
||||||
|
blockRateChange = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return blockRateChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeWhenReady(document) {
|
||||||
|
if (isBlacklisted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isRateChangeBlocked()) {
|
||||||
|
document.body.addEventListener(
|
||||||
|
"ratechange",
|
||||||
|
function(event) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
initializeNow(window.document);
|
initializeNow(window.document);
|
||||||
};
|
};
|
||||||
@@ -502,8 +546,10 @@ function initializeNow(document) {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "attributes":
|
case "attributes":
|
||||||
if (mutation.target.attributes["aria-hidden"] &&
|
if (
|
||||||
mutation.target.attributes["aria-hidden"].value == "false") {
|
mutation.target.attributes["aria-hidden"] &&
|
||||||
|
mutation.target.attributes["aria-hidden"].value == "false"
|
||||||
|
) {
|
||||||
var flattenedNodes = getShadow(document.body);
|
var flattenedNodes = getShadow(document.body);
|
||||||
var node = flattenedNodes.filter(x => x.tagName == "VIDEO")[0];
|
var node = flattenedNodes.filter(x => x.tagName == "VIDEO")[0];
|
||||||
if (node) {
|
if (node) {
|
||||||
@@ -551,6 +597,13 @@ function initializeNow(document) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSpeed(controller, video, speed) {
|
||||||
|
var speedvalue = speed.toFixed(2);
|
||||||
|
video.playbackRate = Number(speedvalue);
|
||||||
|
var speedIndicator = controller.shadowRoot.querySelector("span");
|
||||||
|
speedIndicator.textContent = speedvalue;
|
||||||
|
}
|
||||||
|
|
||||||
function runAction(action, document, value, e) {
|
function runAction(action, document, value, e) {
|
||||||
if (tc.settings.audioBoolean) {
|
if (tc.settings.audioBoolean) {
|
||||||
var mediaTags = getShadow(document.body).filter(x => {
|
var mediaTags = getShadow(document.body).filter(x => {
|
||||||
@@ -592,14 +645,14 @@ function runAction(action, document, value, e) {
|
|||||||
(v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + value,
|
(v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + value,
|
||||||
16
|
16
|
||||||
);
|
);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
setSpeed(controller, v, s);
|
||||||
} else if (action === "slower") {
|
} else if (action === "slower") {
|
||||||
// Video min rate is 0.0625:
|
// Video min rate is 0.0625:
|
||||||
// https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/media/html_media_element.cc?gsn=kMinRate&l=165
|
// https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/media/html_media_element.cc?gsn=kMinRate&l=165
|
||||||
var s = Math.max(v.playbackRate - value, 0.07);
|
var s = Math.max(v.playbackRate - value, 0.07);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
setSpeed(controller, v, s);
|
||||||
} else if (action === "reset") {
|
} else if (action === "reset") {
|
||||||
resetSpeed(v, 1.0);
|
resetSpeed(v, controller, 1.0);
|
||||||
} else if (action === "display") {
|
} else if (action === "display") {
|
||||||
controller.classList.add("vsc-manual");
|
controller.classList.add("vsc-manual");
|
||||||
controller.classList.toggle("vsc-hidden");
|
controller.classList.toggle("vsc-hidden");
|
||||||
@@ -622,7 +675,7 @@ function runAction(action, document, value, e) {
|
|||||||
} else if (action === "drag") {
|
} else if (action === "drag") {
|
||||||
handleDrag(v, controller, e);
|
handleDrag(v, controller, e);
|
||||||
} else if (action === "fast") {
|
} else if (action === "fast") {
|
||||||
resetSpeed(v, value);
|
resetSpeed(v, controller, value);
|
||||||
} else if (action === "pause") {
|
} else if (action === "pause") {
|
||||||
pause(v);
|
pause(v);
|
||||||
} else if (action === "muted") {
|
} else if (action === "muted") {
|
||||||
@@ -644,21 +697,21 @@ function pause(v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetSpeed(v, target) {
|
function resetSpeed(v, controller, target) {
|
||||||
if (v.playbackRate === target) {
|
if (v.playbackRate === target) {
|
||||||
if (v.playbackRate === getKeyBindings("reset")) {
|
if (v.playbackRate === getKeyBindings("reset")) {
|
||||||
// resetSpeed
|
// resetSpeed
|
||||||
if (target !== 1.0) {
|
if (target !== 1.0) {
|
||||||
v.playbackRate = 1.0;
|
setSpeed(controller, v, 1.0);
|
||||||
} else {
|
} else {
|
||||||
v.playbackRate = getKeyBindings("fast"); // fastSpeed
|
setSpeed(controller, v, getKeyBindings("fast")); // fastSpeed
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
v.playbackRate = getKeyBindings("reset"); // resetSpeed
|
setSpeed(controller, v, getKeyBindings("reset")); // resetSpeed
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setKeyBindings("reset", v.playbackRate); // resetSpeed
|
setKeyBindings("reset", v.playbackRate); // resetSpeed
|
||||||
v.playbackRate = target;
|
setSpeed(controller, v, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Video Speed Controller",
|
"name": "Video Speed Controller",
|
||||||
"short_name": "videospeed",
|
"short_name": "videospeed",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
||||||
"homepage_url": "https://github.com/igrigorik/videospeed",
|
"homepage_url": "https://github.com/igrigorik/videospeed",
|
||||||
@@ -29,7 +29,6 @@
|
|||||||
"https://plus.google.com/hangouts/*",
|
"https://plus.google.com/hangouts/*",
|
||||||
"https://hangouts.google.com/*",
|
"https://hangouts.google.com/*",
|
||||||
"https://meet.google.com/*",
|
"https://meet.google.com/*",
|
||||||
"https://teamtreehouse.com/*",
|
|
||||||
"http://www.hitbox.tv/*"
|
"http://www.hitbox.tv/*"
|
||||||
],
|
],
|
||||||
"css": ["inject.css"],
|
"css": ["inject.css"],
|
||||||
|
24
options.html
24
options.html
@@ -160,14 +160,30 @@
|
|||||||
>Blacklisted sites on which extension is disabled<br />
|
>Blacklisted sites on which extension is disabled<br />
|
||||||
(one per line)<br />
|
(one per line)<br />
|
||||||
<br />
|
<br />
|
||||||
<em
|
<em>
|
||||||
><a href="https://www.regexpal.com/">Regex</a> is supported. Be sure
|
<a href="https://www.regexpal.com/">Regex</a> is supported. Be sure
|
||||||
it is in "//g" format.<br />
|
it is in "//g" format.<br />
|
||||||
ie: /(.+)youtube\.com(\/*)$/gi</em
|
ie: /(.+)youtube\.com(\/*)$/gi
|
||||||
>
|
</em>
|
||||||
</label>
|
</label>
|
||||||
<textarea id="blacklist" rows="10" cols="50"></textarea>
|
<textarea id="blacklist" rows="10" cols="50"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label for="blacklistrc">
|
||||||
|
Sites to forcefully block ratechange listeners<br />
|
||||||
|
(add here if video speed can't be adjusted or "bounces back" after
|
||||||
|
changing)<br />
|
||||||
|
<br />
|
||||||
|
<em>
|
||||||
|
*Important: Use sparingly as this may cause unexpected website and
|
||||||
|
extension behavior.
|
||||||
|
</em>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<em><a href="https://www.regexpal.com/">Regex</a> is supported.</em>
|
||||||
|
</label>
|
||||||
|
<textarea id="blacklistrc" rows="10" cols="50"></textarea>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<button id="save">Save</button>
|
<button id="save">Save</button>
|
||||||
|
30
options.js
30
options.js
@@ -23,6 +23,11 @@ var tcDefaults = {
|
|||||||
vine.co
|
vine.co
|
||||||
imgur.com
|
imgur.com
|
||||||
teams.microsoft.com
|
teams.microsoft.com
|
||||||
|
`.replace(regStrip, ""),
|
||||||
|
blacklistrc: `\
|
||||||
|
twitch.tv
|
||||||
|
pluralsight.com
|
||||||
|
teamtreehouse.com
|
||||||
`.replace(regStrip, "")
|
`.replace(regStrip, "")
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -191,7 +196,25 @@ function validate() {
|
|||||||
var regexp = new RegExp(match);
|
var regexp = new RegExp(match);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
status.textContent =
|
status.textContent =
|
||||||
"Error: Invalid Regex: " + match + ". Unable to save";
|
"Error: Invalid blacklist regex: " + match + ". Unable to save";
|
||||||
|
valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document
|
||||||
|
.getElementById("blacklistrc")
|
||||||
|
.value.split("\n")
|
||||||
|
.forEach(match => {
|
||||||
|
match = match.replace(regStrip, "");
|
||||||
|
if (match.startsWith("/")) {
|
||||||
|
try {
|
||||||
|
var regexp = new RegExp(match);
|
||||||
|
} catch (err) {
|
||||||
|
status.textContent =
|
||||||
|
"Error: Invalid ratechange blacklist regex: " +
|
||||||
|
match +
|
||||||
|
". Unable to save";
|
||||||
valid = false;
|
valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,6 +239,7 @@ function save_options() {
|
|||||||
var startHidden = document.getElementById("startHidden").checked;
|
var startHidden = document.getElementById("startHidden").checked;
|
||||||
var controllerOpacity = document.getElementById("controllerOpacity").value;
|
var controllerOpacity = document.getElementById("controllerOpacity").value;
|
||||||
var blacklist = document.getElementById("blacklist").value;
|
var blacklist = document.getElementById("blacklist").value;
|
||||||
|
var blacklistrc = document.getElementById("blacklistrc").value;
|
||||||
|
|
||||||
chrome.storage.sync.remove([
|
chrome.storage.sync.remove([
|
||||||
"resetSpeed",
|
"resetSpeed",
|
||||||
@@ -238,7 +262,8 @@ function save_options() {
|
|||||||
startHidden: startHidden,
|
startHidden: startHidden,
|
||||||
controllerOpacity: controllerOpacity,
|
controllerOpacity: controllerOpacity,
|
||||||
keyBindings: keyBindings,
|
keyBindings: keyBindings,
|
||||||
blacklist: blacklist.replace(regStrip, "")
|
blacklist: blacklist.replace(regStrip, ""),
|
||||||
|
blacklistrc: blacklistrc.replace(regStrip, "")
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
// Update status to let user know options were saved.
|
// Update status to let user know options were saved.
|
||||||
@@ -261,6 +286,7 @@ function restore_options() {
|
|||||||
document.getElementById("controllerOpacity").value =
|
document.getElementById("controllerOpacity").value =
|
||||||
storage.controllerOpacity;
|
storage.controllerOpacity;
|
||||||
document.getElementById("blacklist").value = storage.blacklist;
|
document.getElementById("blacklist").value = storage.blacklist;
|
||||||
|
document.getElementById("blacklistrc").value = storage.blacklistrc;
|
||||||
|
|
||||||
// ensure that there is a "display" binding for upgrades from versions that had it as a separate binding
|
// ensure that there is a "display" binding for upgrades from versions that had it as a separate binding
|
||||||
if (storage.keyBindings.filter(x => x.action == "display").length == 0) {
|
if (storage.keyBindings.filter(x => x.action == "display").length == 0) {
|
||||||
|
Reference in New Issue
Block a user