aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAjay <[email protected]>2022-12-24 00:54:56 -0500
committerAjay <[email protected]>2022-12-24 00:54:56 -0500
commit7dd2c9eb3e4af690024319f32a075fef90bb2d88 (patch)
tree77a3a04d46ae3ed04ace804945a9f6ca3fe7152f
parent7bf17e17461a1d8b3958cb0d9cda223808ebaadd (diff)
downloadSponsorBlock-7dd2c9eb3e4af690024319f32a075fef90bb2d88.tar.gz
SponsorBlock-7dd2c9eb3e4af690024319f32a075fef90bb2d88.zip
Move some generic functions to a new package
-rw-r--r--package-lock.json32
-rw-r--r--package.json3
-rw-r--r--src/components/SponsorTimeEditComponent.tsx23
-rw-r--r--src/content.ts8
-rw-r--r--src/help.ts4
-rw-r--r--src/js-components/previewBar.ts4
-rw-r--r--src/popup.ts5
-rw-r--r--src/render/CategoryPill.tsx11
-rw-r--r--src/utils.ts4
-rw-r--r--src/utils/exporter.ts9
-rw-r--r--src/utils/genericUtils.ts70
-rw-r--r--src/utils/pageUtils.ts4
12 files changed, 71 insertions, 106 deletions
diff --git a/package-lock.json b/package-lock.json
index 9eff316a..29ce129d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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",
diff --git a/package.json b/package.json
index 824abd6a..e96403cf 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/components/SponsorTimeEditComponent.tsx b/src/components/SponsorTimeEditComponent.tsx
index 01bee538..2cd9f984 100644
--- a/src/components/SponsorTimeEditComponent.tsx
+++ b/src/components/SponsorTimeEditComponent.tsx
@@ -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) {
diff --git a/src/content.ts b/src/content.ts
index f98e2ed9..db6d9886 100644
--- a/src/content.ts
+++ b/src/content.ts
@@ -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 + ")";
}
diff --git a/src/help.ts b/src/help.ts
index 9cc6b4bd..10bd86cf 100644
--- a/src/help.ts
+++ b/src/help.ts
@@ -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");
diff --git a/src/js-components/previewBar.ts b/src/js-components/previewBar.ts
index 4842afc0..0afb7f96 100644
--- a/src/js-components/previewBar.ts
+++ b/src/js-components/previewBar.ts
@@ -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;
}
diff --git a/src/popup.ts b/src/popup.ts
index 3584fba5..f631d7cd 100644
--- a/src/popup.ts
+++ b/src/popup.ts
@@ -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)
: "");
}
diff --git a/src/render/CategoryPill.tsx b/src/render/CategoryPill.tsx
index f8ec1791..aeace093 100644
--- a/src/render/CategoryPill.tsx
+++ b/src/render/CategoryPill.tsx
@@ -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"),
diff --git a/src/utils.ts b/src/utils.ts
index 1ee5781d..90bd5418 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -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 */
diff --git a/src/utils/exporter.ts b/src/utils/exporter.ts
index ec67133b..3c2ca6f9 100644
--- a/src/utils/exporter.ts
+++ b/src/utils/exporter.ts
@@ -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,
diff --git a/src/utils/genericUtils.ts b/src/utils/genericUtils.ts
index 144c0438..675f7096 100644
--- a/src/utils/genericUtils.ts
+++ b/src/utils/genericUtils.ts
@@ -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,
diff --git a/src/utils/pageUtils.ts b/src/utils/pageUtils.ts
index 42766fef..beda1585 100644
--- a/src/utils/pageUtils.ts
+++ b/src/utils/pageUtils.ts
@@ -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) {