-
Notifications
You must be signed in to change notification settings - Fork 0
/
skip.js
112 lines (97 loc) · 2.98 KB
/
skip.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Only apply URLs with /lecture/ in them
const lectureUrlRegex = /^https:\/\/www\.coursera\.org\/learn\/uol-[^\/]+\/lecture\//;
// Create live collection of video containers to check.
// Could use querySelector but getElementsByClassName is
// much faster and this has to be checked in every DOM
// mutation so needs to be fast
const containers = document.getElementsByClassName(
"video-main-player-container"
);
let skipSeconds = 9;
let isEnabled = false;
/**
* Sets the extensions toolbar icon
*/
function setIcon(value) {
// If extension is reloaded or updated it will cause
// Extension context invalidated exception
try {
chrome.runtime.sendMessage({
iconPath: `icons/${value}.png`,
});
} catch {}
}
/**
* Video event handler to skip to 9 seconds if current time is less
*/
function skipIntroHandler() {
if (this.currentTime < skipSeconds) {
setIcon("icon-active");
this.currentTime = skipSeconds;
}
}
/**
* Finds the video element and skips the first 9 seconds
*/
function skipIntro() {
// Only run if has a video and is on a lecture URL
if (!containers[0] || !lectureUrlRegex.test(window.location)) {
setIcon("icon-inactive");
return;
}
const video = containers[0].getElementsByTagName("video")[0];
if (video && video.dataset.intro != "skipped") {
video.dataset.intro = "skipped";
// Add events or call the handler if events have already been called
if (video.readyState < 3) {
// loadedmetadata seems to be the correct event to use but doesn't
// always work, looks like Coursera adjusting the time back sometimes?
// Using canplay and canplaythrough seem to mostly fix the issue.
video.addEventListener("loadedmetadata", skipIntroHandler, {
once: true,
});
video.addEventListener("canplay", skipIntroHandler, { once: true });
video.addEventListener("canplaythrough", skipIntroHandler, {
once: true,
});
// Coursera seems to sometimes change the time back so also check on
// first play that has skipped intro
video.addEventListener("play", skipIntroHandler, { once: true });
} else {
skipIntroHandler.call(video);
}
}
}
// Detect react mutations and fix video if needed
const observer = new MutationObserver(skipIntro);
function setEnable(value) {
if (isEnabled == value) {
return;
}
isEnabled = value;
if (value) {
setIcon("icon-inactive");
skipIntro();
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
} else {
setIcon("icon-disabled");
observer.disconnect();
}
}
// Update settings based on changes from options
chrome.storage.onChanged.addListener((changes, area) => {
if (changes.enabled) {
setEnable(changes.enabled.newValue);
}
if (changes.skipSeconds) {
skipSeconds = changes.skipSeconds.newValue;
}
});
// Load current options
storageGet({ skipSeconds: 9, enabled: true }, (data) => {
skipSeconds = data.skipSeconds;
setEnable(data.enabled);
});