Load existing chapters

This commit is contained in:
Ajay
2022-02-22 21:22:30 -05:00
parent cf3b3c5c48
commit 2ebc5489cd
7 changed files with 90 additions and 28 deletions

View File

@@ -1,5 +1,5 @@
/** Function that can be used to wait for a condition before returning. */
async function wait<T>(condition: () => T | false, timeout = 5000, check = 100): Promise<T> {
async function wait<T>(condition: () => T, timeout = 5000, check = 100, predicate?: (obj: T) => boolean): Promise<T> {
return await new Promise((resolve, reject) => {
setTimeout(() => {
clearInterval(interval);
@@ -8,7 +8,7 @@ async function wait<T>(condition: () => T | false, timeout = 5000, check = 100):
const intervalCheck = () => {
const result = condition();
if (result) {
if (predicate ? predicate(result) : result) {
resolve(result);
clearInterval(interval);
}
@@ -21,6 +21,20 @@ async function wait<T>(condition: () => T | false, timeout = 5000, check = 100):
});
}
function getFormattedTimeToSeconds(formatted: string): number | null {
const fragments = /^(?:(?:(\d+):)?(\d+):)?(\d*(?:[.,]\d+)?)$/.exec(formatted);
if (fragments === null) {
return null;
}
const hours = fragments[1] ? parseInt(fragments[1]) : 0;
const minutes = fragments[2] ? parseInt(fragments[2] || '0') : 0;
const seconds = fragments[3] ? parseFloat(fragments[3].replace(',', '.')) : 0;
return hours * 3600 + minutes * 60 + seconds;
}
/**
* Gets the error message in a nice string
*
@@ -64,10 +78,11 @@ function hexToRgb(hex: string): {r: number, g: number, b: number} {
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
}
export const GenericUtils = {
wait,
getFormattedTimeToSeconds,
getErrorMessage,
getLuminance
}

View File

@@ -1,4 +1,7 @@
export function getControls(): HTMLElement | false {
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
import { GenericUtils } from "./genericUtils";
export function getControls(): HTMLElement {
const controlsSelectors = [
// YouTube
".ytp-right-controls",
@@ -16,7 +19,7 @@ export function getControls(): HTMLElement | false {
}
}
return false;
return null;
}
export function isVisible(element: HTMLElement): boolean {
@@ -61,4 +64,42 @@ export function getHashParams(): Record<string, unknown> {
}
return {};
}
export function getExistingChapters(currentVideoID: VideoID, duration: number): SponsorTime[] {
const chaptersBox = document.querySelector("ytd-macro-markers-list-renderer");
const chapters: SponsorTime[] = [];
if (chaptersBox) {
let lastSegment: SponsorTime = null;
const links = chaptersBox.querySelectorAll("ytd-macro-markers-list-item-renderer > a");
for (const link of links) {
const timeElement = link.querySelector("#time") as HTMLElement;
const description = link.querySelector("#details h4") as HTMLElement;
if (timeElement && description?.innerText?.length > 0 && link.getAttribute("href")?.includes(currentVideoID)) {
const time = GenericUtils.getFormattedTimeToSeconds(timeElement.innerText);
if (lastSegment) {
lastSegment.segment[1] = time;
chapters.push(lastSegment);
}
lastSegment = {
segment: [time, null],
category: "chapter" as Category,
actionType: ActionType.Chapter,
description: description.innerText,
source: SponsorSourceType.YouTube,
UUID: null
};
}
}
if (lastSegment) {
lastSegment.segment[1] = duration;
chapters.push(lastSegment);
}
}
return chapters;
}