mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2024-11-10 01:01:55 +01:00
Move some generic functions to a new package
This commit is contained in:
parent
7bf17e1746
commit
7dd2c9eb3e
12 changed files with 71 additions and 106 deletions
32
package-lock.json
generated
32
package-lock.json
generated
|
@ -27,6 +27,7 @@
|
|||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@ajayyy/maze-utils": "^1.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
@ -65,6 +66,32 @@
|
|||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@ajayyy/maze-utils": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@ajayyy/maze-utils/-/maze-utils-1.0.3.tgz",
|
||||
"integrity": "sha512-sdQyU/2VAmJ9FiyUIdjE8FbO5b5IofN9vK/7lkZiUw91V+NZi7aSG/LSYMqmQ3OuTYRE5PLN9Jyknuo2ZnljjA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://sponsor.ajay.app/donate"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ajayyy-org"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/ajayyy"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paypal.me/ajayyy"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
|
@ -13336,6 +13363,11 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@ajayyy/maze-utils": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@ajayyy/maze-utils/-/maze-utils-1.0.3.tgz",
|
||||
"integrity": "sha512-sdQyU/2VAmJ9FiyUIdjE8FbO5b5IofN9vK/7lkZiUw91V+NZi7aSG/LSYMqmQ3OuTYRE5PLN9Jyknuo2ZnljjA=="
|
||||
},
|
||||
"@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"@ajayyy/maze-utils": "^1.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chrome": "^0.0.199",
|
||||
|
|
|
@ -6,10 +6,9 @@ import Utils from "../utils";
|
|||
import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
|
||||
import { RectangleTooltip } from "../render/RectangleTooltip";
|
||||
import SelectorComponent, { SelectorOption } from "./SelectorComponent";
|
||||
import { GenericUtils } from "../utils/genericUtils";
|
||||
import { noRefreshFetchingChaptersAllowed } from "../utils/licenseKey";
|
||||
import { DEFAULT_CATEGORY } from "../utils/categoryUtils";
|
||||
|
||||
import { getFormattedTime, getFormattedTimeToSeconds } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
const utils = new Utils();
|
||||
|
||||
|
@ -181,9 +180,9 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
style={timeDisplayStyle}
|
||||
className="sponsorTimeDisplay"
|
||||
onClick={this.toggleEditTime.bind(this)}>
|
||||
{GenericUtils.getFormattedTime(segment[0], true) +
|
||||
{getFormattedTime(segment[0], true) +
|
||||
((!isNaN(segment[1]) && sponsorTime.actionType !== ActionType.Poi)
|
||||
? " " + chrome.i18n.getMessage("to") + " " + GenericUtils.getFormattedTime(segment[1], true) : "")}
|
||||
? " " + chrome.i18n.getMessage("to") + " " + getFormattedTime(segment[1], true) : "")}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -308,8 +307,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
const sponsorTimeEdits = this.state.sponsorTimeEdits;
|
||||
|
||||
// check if change is small engough to show tooltip
|
||||
const before = GenericUtils.getFormattedTimeToSeconds(sponsorTimeEdits[index]);
|
||||
const after = GenericUtils.getFormattedTimeToSeconds(targetValue);
|
||||
const before = getFormattedTimeToSeconds(sponsorTimeEdits[index]);
|
||||
const after = getFormattedTimeToSeconds(targetValue);
|
||||
const difference = Math.abs(before - after);
|
||||
if (0 < difference && difference < 0.5) this.showScrollToEditToolTip();
|
||||
|
||||
|
@ -333,7 +332,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
}
|
||||
|
||||
const sponsorTimeEdits = this.state.sponsorTimeEdits;
|
||||
let timeAsNumber = GenericUtils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[index]);
|
||||
let timeAsNumber = getFormattedTimeToSeconds(this.state.sponsorTimeEdits[index]);
|
||||
if (timeAsNumber !== null && e.deltaY != 0) {
|
||||
if (e.deltaY < 0) {
|
||||
timeAsNumber += step;
|
||||
|
@ -343,7 +342,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
timeAsNumber = 0;
|
||||
}
|
||||
|
||||
sponsorTimeEdits[index] = GenericUtils.getFormattedTime(timeAsNumber, true);
|
||||
sponsorTimeEdits[index] = getFormattedTime(timeAsNumber, true);
|
||||
if (sponsorTime.actionType === ActionType.Poi) sponsorTimeEdits[1] = sponsorTimeEdits[0];
|
||||
|
||||
this.setState({sponsorTimeEdits});
|
||||
|
@ -575,8 +574,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
|
||||
/** Returns an array in the sponsorTimeEdits form (formatted time string) from a normal seconds sponsor time */
|
||||
getFormattedSponsorTimesEdits(sponsorTime: SponsorTime): [string, string] {
|
||||
return [GenericUtils.getFormattedTime(sponsorTime.segment[0], true),
|
||||
GenericUtils.getFormattedTime(sponsorTime.segment[1], true)];
|
||||
return [getFormattedTime(sponsorTime.segment[0], true),
|
||||
getFormattedTime(sponsorTime.segment[1], true)];
|
||||
}
|
||||
|
||||
saveEditTimes(): void {
|
||||
|
@ -584,8 +583,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||
const category = this.categoryOptionRef.current.value as Category
|
||||
|
||||
if (this.state.editing) {
|
||||
const startTime = GenericUtils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]);
|
||||
const endTime = GenericUtils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1]);
|
||||
const startTime = getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]);
|
||||
const endTime = getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1]);
|
||||
|
||||
// Change segment time only if the format was correct
|
||||
if (startTime !== null && endTime !== null) {
|
||||
|
|
|
@ -39,6 +39,8 @@ import { ChapterVote } from "./render/ChapterVote";
|
|||
import { openWarningDialog } from "./utils/warnings";
|
||||
import { Tooltip } from "./render/Tooltip";
|
||||
import { noRefreshFetchingChaptersAllowed } from "./utils/licenseKey";
|
||||
import { waitFor } from "@ajayyy/maze-utils";
|
||||
import { getFormattedTime } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
const utils = new Utils();
|
||||
|
||||
|
@ -1203,7 +1205,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
|||
|
||||
function importExistingChapters(wait: boolean) {
|
||||
if (!existingChaptersImported) {
|
||||
GenericUtils.wait(() => video?.duration && getExistingChapters(sponsorVideoID, video.duration),
|
||||
waitFor(() => video?.duration && getExistingChapters(sponsorVideoID, video.duration),
|
||||
wait ? 5000 : 0, 100, (c) => c?.length > 0).then((chapters) => {
|
||||
if (!existingChaptersImported && chapters?.length > 0) {
|
||||
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
|
||||
|
@ -2364,7 +2366,7 @@ function getSegmentsMessage(sponsorTimes: SponsorTime[]): string {
|
|||
|
||||
for (let i = 0; i < sponsorTimes.length; i++) {
|
||||
for (let s = 0; s < sponsorTimes[i].segment.length; s++) {
|
||||
let timeMessage = GenericUtils.getFormattedTime(sponsorTimes[i].segment[s]);
|
||||
let timeMessage = getFormattedTime(sponsorTimes[i].segment[s]);
|
||||
//if this is an end time
|
||||
if (s == 1) {
|
||||
timeMessage = " " + chrome.i18n.getMessage("to") + " " + timeMessage;
|
||||
|
@ -2592,7 +2594,7 @@ function showTimeWithoutSkips(skippedDuration: number): void {
|
|||
display.appendChild(duration);
|
||||
}
|
||||
|
||||
const durationAfterSkips = GenericUtils.getFormattedTime(video?.duration - skippedDuration);
|
||||
const durationAfterSkips = getFormattedTime(video?.duration - skippedDuration);
|
||||
|
||||
duration.innerText = (durationAfterSkips == null || skippedDuration <= 0) ? "" : " (" + durationAfterSkips + ")";
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ import Config from "./config";
|
|||
import { showDonationLink } from "./utils/configUtils";
|
||||
|
||||
import { localizeHtmlPage } from "./utils/pageUtils";
|
||||
import { GenericUtils } from "./utils/genericUtils";
|
||||
import { waitFor } from "@ajayyy/maze-utils";
|
||||
|
||||
window.addEventListener('DOMContentLoaded', init);
|
||||
|
||||
async function init() {
|
||||
localizeHtmlPage();
|
||||
|
||||
await GenericUtils.wait(() => Config.config !== null);
|
||||
await waitFor(() => Config.config !== null);
|
||||
|
||||
if (!Config.config.darkMode) {
|
||||
document.documentElement.setAttribute("data-theme", "light");
|
||||
|
|
|
@ -11,8 +11,8 @@ import { ActionType, Category, SegmentContainer, SponsorHideType, SponsorSourceT
|
|||
import { partition } from "../utils/arrayUtils";
|
||||
import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
|
||||
import { normalizeChapterName } from "../utils/exporter";
|
||||
import { GenericUtils } from "../utils/genericUtils";
|
||||
import { findValidElement } from "../utils/pageUtils";
|
||||
import { getFormattedTimeToSeconds } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
||||
const MIN_CHAPTER_SIZE = 0.003;
|
||||
|
@ -140,7 +140,7 @@ class PreviewBar {
|
|||
const tooltipText = tooltipTextElement.textContent;
|
||||
if (tooltipText === null || tooltipText.length === 0) continue;
|
||||
|
||||
timeInSeconds = GenericUtils.getFormattedTimeToSeconds(tooltipText);
|
||||
timeInSeconds = getFormattedTimeToSeconds(tooltipText);
|
||||
|
||||
if (timeInSeconds !== null) break;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import { localizeHtmlPage } from "./utils/pageUtils";
|
|||
import { exportTimes } from "./utils/exporter";
|
||||
import GenericNotice from "./render/GenericNotice";
|
||||
import { noRefreshFetchingChaptersAllowed } from "./utils/licenseKey";
|
||||
import { getFormattedTime } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
const utils = new Utils();
|
||||
|
||||
|
@ -593,9 +594,9 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||
if (downloadedTimes[i].actionType === ActionType.Full) {
|
||||
segmentTimeFromToNode.innerText = chrome.i18n.getMessage("full");
|
||||
} else {
|
||||
segmentTimeFromToNode.innerText = GenericUtils.getFormattedTime(downloadedTimes[i].segment[0], true) +
|
||||
segmentTimeFromToNode.innerText = getFormattedTime(downloadedTimes[i].segment[0], true) +
|
||||
(actionType !== ActionType.Poi
|
||||
? " " + chrome.i18n.getMessage("to") + " " + GenericUtils.getFormattedTime(downloadedTimes[i].segment[1], true)
|
||||
? " " + chrome.i18n.getMessage("to") + " " + getFormattedTime(downloadedTimes[i].segment[1], true)
|
||||
: "");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ import CategoryPillComponent, { CategoryPillState } from "../components/Category
|
|||
import Config from "../config";
|
||||
import { VoteResponse } from "../messageTypes";
|
||||
import { Category, SegmentUUID, SponsorTime } from "../types";
|
||||
import { GenericUtils } from "../utils/genericUtils";
|
||||
import { Tooltip } from "./Tooltip";
|
||||
import { waitFor } from "@ajayyy/maze-utils";
|
||||
import { getYouTubeTitleNode } from "@ajayyy/maze-utils/lib/elements";
|
||||
|
||||
export class CategoryPill {
|
||||
container: HTMLElement;
|
||||
|
@ -23,9 +24,7 @@ export class CategoryPill {
|
|||
async attachToPage(onMobileYouTube: boolean, onInvidious: boolean,
|
||||
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>): Promise<void> {
|
||||
const referenceNode =
|
||||
await GenericUtils.wait(() =>
|
||||
// New YouTube Title, YouTube, Mobile YouTube, Invidious
|
||||
document.querySelector("#title h1, .ytd-video-primary-info-renderer.title, .slim-video-information-title, #player-container + .h-box > h1") as HTMLElement);
|
||||
await waitFor(() => getYouTubeTitleNode());
|
||||
|
||||
if (referenceNode && !referenceNode.contains(this.container)) {
|
||||
this.container = document.createElement('span');
|
||||
|
@ -43,7 +42,7 @@ export class CategoryPill {
|
|||
this.root.render(<CategoryPillComponent ref={this.ref} vote={vote} />);
|
||||
|
||||
if (this.unsavedState) {
|
||||
GenericUtils.wait(() => this.ref.current).then(() => {
|
||||
waitFor(() => this.ref.current).then(() => {
|
||||
this.ref.current?.setState(this.unsavedState);
|
||||
this.unsavedState = null;
|
||||
});
|
||||
|
@ -99,7 +98,7 @@ export class CategoryPill {
|
|||
if (!Config.config.categoryPillUpdate) {
|
||||
Config.config.categoryPillUpdate = true;
|
||||
|
||||
const watchDiv = await GenericUtils.wait(() => document.querySelector("#info.ytd-watch-flexy") as HTMLElement);
|
||||
const watchDiv = await waitFor(() => document.querySelector("#info.ytd-watch-flexy") as HTMLElement);
|
||||
if (watchDiv) {
|
||||
new Tooltip({
|
||||
text: chrome.i18n.getMessage("categoryPillNewFeature"),
|
||||
|
|
|
@ -3,7 +3,7 @@ import { CategorySelection, SponsorTime, FetchResponse, BackgroundScriptContaine
|
|||
|
||||
import * as CompileConfig from "../config.json";
|
||||
import { findValidElement, findValidElementFromSelector } from "./utils/pageUtils";
|
||||
import { GenericUtils } from "./utils/genericUtils";
|
||||
import { waitFor } from "@ajayyy/maze-utils";
|
||||
|
||||
export default class Utils {
|
||||
|
||||
|
@ -31,7 +31,7 @@ export default class Utils {
|
|||
}
|
||||
|
||||
async wait<T>(condition: () => T, timeout = 5000, check = 100): Promise<T> {
|
||||
return GenericUtils.wait(condition, timeout, check);
|
||||
return waitFor(condition, timeout, check);
|
||||
}
|
||||
|
||||
/* Uses a mutation observer to wait asynchronously */
|
||||
|
|
|
@ -2,6 +2,7 @@ import { ActionType, Category, SegmentUUID, SponsorSourceType, SponsorTime } fro
|
|||
import { shortCategoryName } from "./categoryUtils";
|
||||
import { GenericUtils } from "./genericUtils";
|
||||
import * as CompileConfig from "../../config.json";
|
||||
import { getFormattedTime, getFormattedTimeToSeconds } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
const inTest = typeof chrome === "undefined";
|
||||
|
||||
|
@ -26,9 +27,9 @@ export function exportTimes(segments: SponsorTime[]): string {
|
|||
function exportTime(segment: SponsorTime): string {
|
||||
const name = segment.description || shortCategoryName(segment.category);
|
||||
|
||||
return `${GenericUtils.getFormattedTime(segment.segment[0], true)}${
|
||||
return `${getFormattedTime(segment.segment[0], true)}${
|
||||
segment.segment[1] && segment.segment[0] !== segment.segment[1]
|
||||
? ` - ${GenericUtils.getFormattedTime(segment.segment[1], true)}` : ""} ${name}`;
|
||||
? ` - ${getFormattedTime(segment.segment[1], true)}` : ""} ${name}`;
|
||||
}
|
||||
|
||||
export function importTimes(data: string, videoDuration: number): SponsorTime[] {
|
||||
|
@ -37,7 +38,7 @@ export function importTimes(data: string, videoDuration: number): SponsorTime[]
|
|||
for (const line of lines) {
|
||||
const match = line.match(/(?:((?:\d+:)?\d+:\d+)+(?:\.\d+)?)|(?:\d+(?=s| second))/g);
|
||||
if (match) {
|
||||
const startTime = GenericUtils.getFormattedTimeToSeconds(match[0]);
|
||||
const startTime = getFormattedTimeToSeconds(match[0]);
|
||||
if (startTime !== null) {
|
||||
// Remove "seconds", "at", special characters, and ")" if there was a "("
|
||||
const specialCharsMatcher = /^(?:\s+seconds?)?[-:()\s]*|(?:\s+at)?[-:(\s]+$|(?<=^\s*\(.+)[-:()\s]*$/g
|
||||
|
@ -51,7 +52,7 @@ export function importTimes(data: string, videoDuration: number): SponsorTime[]
|
|||
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
|
||||
|
||||
const segment: SponsorTime = {
|
||||
segment: [startTime, GenericUtils.getFormattedTimeToSeconds(match[1])],
|
||||
segment: [startTime, getFormattedTimeToSeconds(match[1])],
|
||||
category: determinedCategory ?? ("chapter" as Category),
|
||||
actionType: determinedCategory ? ActionType.Skip : ActionType.Chapter,
|
||||
description: title,
|
||||
|
|
|
@ -1,70 +1,3 @@
|
|||
/** Function that can be used to wait for a condition before returning. */
|
||||
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);
|
||||
reject("TIMEOUT");
|
||||
}, timeout);
|
||||
|
||||
const intervalCheck = () => {
|
||||
const result = condition();
|
||||
if (predicate ? predicate(result) : result) {
|
||||
resolve(result);
|
||||
clearInterval(interval);
|
||||
}
|
||||
};
|
||||
|
||||
const interval = setInterval(intervalCheck, check);
|
||||
|
||||
//run the check once first, this speeds it up a lot
|
||||
intervalCheck();
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function getFormattedTime(seconds: number, precise?: boolean): string {
|
||||
seconds = Math.max(seconds, 0);
|
||||
|
||||
const hours = Math.floor(seconds / 60 / 60);
|
||||
const minutes = Math.floor(seconds / 60) % 60;
|
||||
let minutesDisplay = String(minutes);
|
||||
let secondsNum = seconds % 60;
|
||||
if (!precise) {
|
||||
secondsNum = Math.floor(secondsNum);
|
||||
}
|
||||
|
||||
let secondsDisplay = String(precise ? secondsNum.toFixed(3) : secondsNum);
|
||||
|
||||
if (secondsNum < 10) {
|
||||
//add a zero
|
||||
secondsDisplay = "0" + secondsDisplay;
|
||||
}
|
||||
if (hours && minutes < 10) {
|
||||
//add a zero
|
||||
minutesDisplay = "0" + minutesDisplay;
|
||||
}
|
||||
if (isNaN(hours) || isNaN(minutes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const formatted = (hours ? hours + ":" : "") + minutesDisplay + ":" + secondsDisplay;
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error message in a nice string
|
||||
*
|
||||
|
@ -148,9 +81,6 @@ function generateUserID(length = 36): string {
|
|||
}
|
||||
|
||||
export const GenericUtils = {
|
||||
wait,
|
||||
getFormattedTime,
|
||||
getFormattedTimeToSeconds,
|
||||
getErrorMessage,
|
||||
getLuminance,
|
||||
generateUserID,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { GenericUtils } from "./genericUtils";
|
||||
import { getFormattedTimeToSeconds } from "@ajayyy/maze-utils/lib/formating";
|
||||
|
||||
export function getControls(): HTMLElement {
|
||||
const controlsSelectors = [
|
||||
|
@ -80,7 +80,7 @@ export function getExistingChapters(currentVideoID: VideoID, duration: number):
|
|||
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);
|
||||
const time = getFormattedTimeToSeconds(timeElement.innerText);
|
||||
if (time === null) return [];
|
||||
|
||||
if (lastSegment) {
|
||||
|
|
Loading…
Reference in a new issue