Compare commits

...

29 Commits

Author SHA1 Message Date
Ajay
6cd697dc32 bump version 2023-08-25 16:03:33 -04:00
Ajay
9946bd1af2 Use chromep in another spot 2023-08-25 16:03:17 -04:00
Ajay
3b06d72270 Fix invidious support of Firefox 2023-08-25 16:01:11 -04:00
Ajay
4bd0556464 Remove webnavigation optional permission from firefox 2023-08-23 22:44:41 -04:00
Ajay
7e12a914d5 bump translations 2023-08-22 23:29:01 -04:00
Ajay
25eaf4fa20 bump version 2023-08-22 23:26:21 -04:00
Ajay
b3efa1f787 Add compatibility with video speed controller extension 2023-08-22 15:23:04 -04:00
Ajay
9a18e70e34 Fix rate change listener not set up properly
Fixes #1820
2023-08-22 15:22:03 -04:00
Ajay
64ece9cb73 Fix chrome api being used in tests 2023-08-14 11:49:51 -04:00
Ajay
66c974b011 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2023-08-14 09:28:58 -04:00
Ajay
d8cc93c841 Fix for Firefox not offering promise based APIs in mv2 2023-08-14 09:28:56 -04:00
Ajay Ramachandran
de22accfda Merge pull request #1828 from mchangrh/contributing-translations
add translations to contributing
2023-08-13 15:13:24 -04:00
Michael C
e5b0b60dde add translations to contributing 2023-08-13 15:05:08 -04:00
Ajay Ramachandran
32d98e6544 Add more info about testing on android 2023-08-11 22:38:38 -04:00
Ajay
3dde05eda2 Add more theme icons for browser popup 2023-08-11 21:33:38 -04:00
Ajay
6aeefaae64 Don't reregister contentscripts if not necessary 2023-08-11 12:39:48 -04:00
Ajay
93d695e6c2 Fix error sending messages to closed popups 2023-08-11 12:15:05 -04:00
Ajay
160924feee Update maze utils to improve performance on Invidious, and fix preview bar error
thanks @raphj
2023-08-11 12:08:19 -04:00
Ajay
e3f3ed20e6 Enable non persistent background page on Firefox 2023-08-11 11:39:06 -04:00
Ajay
52149f4c0f bump version 2023-08-09 18:30:21 -04:00
Ajay
cbc586f9ac Potential fix for ctrl+click having a blank html video
Other potential fix for #1820
2023-08-09 18:30:05 -04:00
Ajay
fc8e20be0d Impove incorrect video check, and add better logging to it
Potential fix for #1820
2023-08-09 18:24:21 -04:00
Ajay
368059eb0d bump version 2023-08-01 22:45:53 -04:00
Ajay
ea77375fcc Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2023-08-01 22:45:37 -04:00
Ajay
16005e417d Remove maze utils symlink 2023-08-01 22:45:01 -04:00
Ajay Ramachandran
7c5b750264 use npm ci for consistency 2023-08-01 19:57:07 -04:00
Ajay Ramachandran
cc6b65c6c4 suggest using Linux 2023-08-01 15:52:50 -04:00
Ajay Ramachandran
d2c99c2d77 Merge pull request #1815 from mchangrh/contributing-update
[docs] move building from readme, formatting tweaks
2023-08-01 15:51:39 -04:00
Michael C
84c25e3042 [docs] move building to readme, formatting tweaks
- reformatted windows build issues
- updated contributing to reflect LGPL-3.0-or-later
- replaced Invidio.us with Invidious
- replaced API docs link
- updated Invidious API link
2023-08-01 15:20:24 -04:00
34 changed files with 236 additions and 165 deletions

View File

@@ -1,15 +1,31 @@
If you make any contributions to SponsorBlock after this file was created, you are agreeing that any code you have contributed will be licensed under LGPL-3.0.
If you make any contributions to SponsorBlock after this file was created, you are agreeing that any code you have contributed will be licensed under LGPL-3.0 or later.
# All Platforms
Make sure to pull and update all submodules
`git submodule update --init --recursive`
# Translations
https://crowdin.com/project/sponsorblock
"? property does not exist on type ConfigClass"
> Make sure to copy `config.json.example` to `config.json` and remove comments
# Building
## Building locally
0. You must have [Node.js 16 or later](https://nodejs.org/) and npm installed. Works best on Linux
1. Clone with submodules
```bash
git clone --recursive https://github.com/ajayyy/SponsorBlock
```
Or if you already cloned it, pull submodules with
```bash
git submodule update --init --recursive
```
2. Copy the file `config.json.example` to `config.json` and adjust configuration as desired.
- Comments are invalid in JSON, make sure they are all removed.
- You will need to repeat this step in the future if you get build errors related to `CompileConfig` or `property does not exist on type ConfigClass`. This can happen for example when a new category is added.
3. Run `npm ci` in the repository to install dependencies.
4. Run `npm run build:dev` (for Chrome) or `npm run build:dev:firefox` (for Firefox) to generate a development version of the extension with source maps.
- You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build.
5. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or convert it to a zip file to load it as a [temporary extension](https://developer.mozilla.org/docs/Tools/about:debugging#loading_a_temporary_extension) in Firefox.
## Developing with a clean profile and hot reloading
Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the extension using a clean browser profile with hot reloading. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
Known chromium bug: Extension is not loaded properly on first start. Visit `chrome://extensions/` and reload the extension.
For Firefox for Android, use `npm run dev:firefox-android -- --adb-device <ip-address of the device>`. See the [Firefox documentation](https://extensionworkshop.com/documentation/develop/developing-extensions-for-firefox-for-android/#debug-your-extension) for more information. You may need to edit package.json and add the parameters directly there.
# Windows
"Cannot find module "../maze-utils"
- Enable "Developer Mode" in windows for symlinks
- `src/maze-utils` will not appear properly and builds will fail since it is is only rendered as a file
- Enable symlink support in git `git config --global core.symlinks true`
- run `git checkout -- src/maze-utils` in order to create a symlink instead of a text file

View File

@@ -38,7 +38,7 @@
SponsorBlock is an open-source crowdsourced browser extension to skip sponsor segments in YouTube videos. Users submit when a sponsor happens from the extension, and the extension automatically skips sponsors it knows about. It also supports skipping other categories, such as intros, outros and reminders to subscribe.
It also supports Invidio.us.
It also supports Invidious.
**Translate:** [![Crowdin](https://badges.crowdin.net/sponsorblock/localized.svg)](https://crowdin.com/project/sponsorblock)
@@ -56,47 +56,14 @@ The dataset and API are now being used in some [ports](https://github.com/ajayyy
# API
You can read the API docs [here](https://wiki.sponsor.ajay.app/index.php/API_Docs).
You can read the API docs [here](https://wiki.sponsor.ajay.app/w/API_Docs).
# Building
You must have [Node.js 16](https://nodejs.org/) and npm installed.
1. Clone with submodules
```bash
git clone --recursive https://github.com/ajayyy/SponsorBlock
```
Or if you already cloned it, pull submodules with
```bash
git submodule update --init --recursive
```
2. Copy the file `config.json.example` to `config.json` and adjust configuration as desired.
- You will need to repeat this step in the future if you get build errors related to `CompileConfig`. This can happen for example when a new category is added.
3. Run `npm install` in the repository to install dependencies.
4. Run `npm run build:dev` (for Chrome) or `npm run build:dev:firefox` (for Firefox) to generate a development version of the extension with source maps.
- You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build.
5. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or convert it to a zip file to load it as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension) in Firefox.
### Developing with a clean profile and hot reloading
Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the extension using a clean browser profile with hot reloading. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
Known chromium bug: Extension is not loaded properly on first start. Visit `chrome://extensions/` and reload the extension.
For Firefox for Android, use `npm run dev:firefox-android -- --adb-device <ip-address of the device>`. See the [Firefox documentation](https://extensionworkshop.com/documentation/develop/developing-extensions-for-firefox-for-android/#debug-your-extension) for more information.
See [CONTRIBUTING.md](CONTRIBUTING.md)
# Credit
The awesome [Invidious API](https://docs.invidious.io/API.md) was previously used, and the server is now using [NewLeaf](https://git.sr.ht/~cadence/NewLeaf) as a to get video info from YouTube.
The awesome [Invidious API](https://docs.invidious.io/) was previously used, and the server is now using [NewLeaf](https://git.sr.ht/~cadence/NewLeaf) as a to get video info from YouTube.
Originally forked from [YTSponsorSkip](https://github.com/NDevTK/YTSponsorSkip), but very little code remains.

View File

@@ -1,6 +1,7 @@
{
"optional_permissions": [
"declarativeContent"
"declarativeContent",
"webNavigation"
],
"background": {
"persistent": false

View File

@@ -3,5 +3,11 @@
"gecko": {
"id": "sponsorBlocker@ajay.app"
}
}
},
"background": {
"persistent": false
},
"permissions": [
"scripting"
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "SponsorBlock",
"version": "5.4.13",
"version": "5.4.17",
"default_locale": "en",
"description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app",
@@ -84,8 +84,7 @@
"https://sponsor.ajay.app/*"
],
"optional_permissions": [
"*://*/*",
"webNavigation"
"*://*/*"
],
"browser_action": {
"default_title": "SponsorBlock",
@@ -116,6 +115,21 @@
"light": "icons/IconSponsorBlocker128px.png",
"dark": "icons/IconSponsorBlocker128px.png",
"size": 128
},
{
"light": "icons/IconSponsorBlocker256px.png",
"dark": "icons/IconSponsorBlocker256px.png",
"size": 256
},
{
"light": "icons/IconSponsorBlocker512px.png",
"dark": "icons/IconSponsorBlocker512px.png",
"size": 512
},
{
"light": "icons/IconSponsorBlocker1024px.png",
"dark": "icons/IconSponsorBlocker1024px.png",
"size": 1024
}
]
},

View File

@@ -1,5 +1,11 @@
{
"background": {
"persistent": false
}
},
"permissions": [
"scripting"
],
"optional_permissions": [
"webNavigation"
]
}

View File

@@ -3,9 +3,9 @@ import * as CompileConfig from "../config.json";
import Config from "./config";
import { Registration } from "./types";
import "content-scripts-register-polyfill";
import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "./maze-utils/background-request-proxy";
import { setupTabUpdates } from "./maze-utils/tab-updates";
import { generateUserID } from "./maze-utils/setup";
import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "../maze-utils/src/background-request-proxy";
import { setupTabUpdates } from "../maze-utils/src/tab-updates";
import { generateUserID } from "../maze-utils/src/setup";
// Make the config public for debugging purposes
@@ -13,9 +13,10 @@ window.SB = Config;
import Utils from "./utils";
import { getExtensionIdsToImportFrom } from "./utils/crossExtension";
import { isFirefoxOrSafari } from "./maze-utils";
import { injectUpdatedScripts } from "./maze-utils/cleanup";
import { isFirefoxOrSafari } from "../maze-utils/src";
import { injectUpdatedScripts } from "../maze-utils/src/cleanup";
import { logWarn } from "./utils/logger";
import { chromeP } from "../maze-utils/src/browserApi";
const utils = new Utils({
registerFirefoxContentScript,
unregisterFirefoxContentScript
@@ -27,7 +28,7 @@ const popupPort: Record<string, chrome.runtime.Port> = {};
const contentScriptRegistrations = {};
// Register content script if needed
utils.wait(() => Config.config !== null).then(function() {
utils.wait(() => Config.isReady()).then(function() {
if (Config.config.supportInvidious) utils.setupExtraSiteContentScripts();
});
@@ -75,7 +76,11 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
case "infoUpdated":
case "videoChanged":
if (sender.tab) {
popupPort[sender.tab.id]?.postMessage(request);
try {
popupPort[sender.tab.id]?.postMessage(request);
} catch (e) {
// This can happen if the popup is closed
}
}
return false;
default:
@@ -148,27 +153,60 @@ chrome.runtime.onInstalled.addListener(function () {
*
* @param {JSON} options
*/
function registerFirefoxContentScript(options: Registration) {
const oldRegistration = contentScriptRegistrations[options.id];
if (oldRegistration) oldRegistration.unregister();
async function registerFirefoxContentScript(options: Registration) {
if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
const existingRegistrations = await chromeP.scripting.getRegisteredContentScripts({
ids: [options.id]
});
if (existingRegistrations.length > 0
&& existingRegistrations[0].matches.every((match) => options.matches.includes(match))) {
// No need to register another script, already registered
return;
}
}
await unregisterFirefoxContentScript(options.id);
if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
await chromeP.scripting.registerContentScripts([{
id: options.id,
runAt: "document_start",
matches: options.matches,
allFrames: options.allFrames,
js: options.js,
css: options.css,
persistAcrossSessions: true,
}]);
} else {
chrome.contentScripts.register({
allFrames: options.allFrames,
js: options.js?.map?.(file => ({file})),
css: options.css?.map?.(file => ({file})),
matches: options.matches
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
}
chrome.contentScripts.register({
allFrames: options.allFrames,
js: options.js,
css: options.css,
matches: options.matches
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
}
/**
* Only works on Firefox.
* Firefox requires that this is handled by the background script
*
*/
function unregisterFirefoxContentScript(id: string) {
if (contentScriptRegistrations[id]) {
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
async function unregisterFirefoxContentScript(id: string) {
if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
try {
await chromeP.scripting.unregisterContentScripts({
ids: [id]
});
} catch (e) {
// Already registered
}
} else {
if (contentScriptRegistrations[id]) {
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
}
}
}

View File

@@ -8,7 +8,7 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { VoteResponse } from "../messageTypes";
import { AnimationUtils } from "../utils/animationUtils";
import { Tooltip } from "../render/Tooltip";
import { getErrorMessage } from "../maze-utils/formating";
import { getErrorMessage } from "../../maze-utils/src/formating";
export interface CategoryPillProps {
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;

View File

@@ -8,7 +8,7 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { VoteResponse } from "../messageTypes";
import { AnimationUtils } from "../utils/animationUtils";
import { Tooltip } from "../render/Tooltip";
import { getErrorMessage } from "../maze-utils/formating";
import { getErrorMessage } from "../../maze-utils/src/formating";
export interface ChapterVoteProps {
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;

View File

@@ -12,8 +12,8 @@ import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
import PencilSvg from "../svg-icons/pencil_svg";
import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { generateUserID } from "../maze-utils/setup";
import { keybindToString } from "../maze-utils/config";
import { generateUserID } from "../../maze-utils/src/setup";
import { keybindToString } from "../../maze-utils/src/config";
enum SkipButtonState {
Undo, // Unskip

View File

@@ -7,7 +7,7 @@ import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
import { RectangleTooltip } from "../render/RectangleTooltip";
import SelectorComponent, { SelectorOption } from "./SelectorComponent";
import { DEFAULT_CATEGORY } from "../utils/categoryUtils";
import { getFormattedTime, getFormattedTimeToSeconds } from "../maze-utils/formating";
import { getFormattedTime, getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
const utils = new Utils();

View File

@@ -2,7 +2,7 @@ import * as React from "react";
import { createRoot, Root } from 'react-dom/client';
import Config from "../../config";
import KeybindDialogComponent from "./KeybindDialogComponent";
import { formatKey, Keybind, keybindEquals, keybindToString } from "../../maze-utils/config";
import { formatKey, Keybind, keybindEquals, keybindToString } from "../../../maze-utils/src/config";
export interface KeybindProps {
option: string;

View File

@@ -1,7 +1,7 @@
import * as React from "react";
import { ChangeEvent } from "react";
import Config from "../../config";
import { Keybind, formatKey, keybindEquals } from "../../maze-utils/config";
import { Keybind, formatKey, keybindEquals } from "../../../maze-utils/src/config";
export interface KeybindDialogProps {
option: string;

View File

@@ -1,8 +1,8 @@
import * as CompileConfig from "../config.json";
import * as invidiousList from "../ci/invidiouslist.json";
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, VideoID, SponsorHideType } from "./types";
import { Keybind, ProtoConfig, keybindEquals } from "./maze-utils/config";
import { HashedValue } from "./maze-utils/hash";
import { Keybind, ProtoConfig, keybindEquals } from "../maze-utils/src/config";
import { HashedValue } from "../maze-utils/src/hash";
export interface Permission {
canSubmit: boolean;

View File

@@ -32,21 +32,21 @@ import { logDebug } from "./utils/logger";
import { importTimes } from "./utils/exporter";
import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings";
import { isFirefoxOrSafari, waitFor } from "./maze-utils";
import { getErrorMessage, getFormattedTime } from "./maze-utils/formating";
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "./maze-utils/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals } from "./maze-utils/config";
import { findValidElement, waitForElement } from "./maze-utils/dom"
import { getHash, HashedValue } from "./maze-utils/hash";
import { generateUserID } from "./maze-utils/setup";
import { updateAll } from "./maze-utils/thumbnailManagement";
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "../maze-utils/src/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals } from "../maze-utils/src/config";
import { findValidElement, waitForElement } from "../maze-utils/src/dom"
import { getHash, HashedValue } from "../maze-utils/src/hash";
import { generateUserID } from "../maze-utils/src/setup";
import { updateAll } from "../maze-utils/src/thumbnailManagement";
import { setupThumbnailListener } from "./utils/thumbnails";
import * as documentScript from "../dist/js/document.js";
import { Tooltip } from "./render/Tooltip";
import { isDeArrowInstalled } from "./utils/crossExtension";
import { runCompatibilityChecks } from "./utils/compatibility";
import { cleanPage } from "./utils/pageCleaner";
import { addCleanupListener } from "./maze-utils/cleanup";
import { addCleanupListener } from "../maze-utils/src/cleanup";
cleanPage();
@@ -803,11 +803,12 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
const currentVideoID = getYouTubeVideoID();
const recordedVideoID = videoID || getVideoID();
if (currentVideoID !== recordedVideoID || (sponsorTime
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment === sponsorTime.segment))
&& !sponsorTimesSubmitting.some((time) => time.segment === sponsorTime.segment))) {
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))
&& !sponsorTimesSubmitting.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))) {
// Something has really gone wrong
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
console.error("[SponsorBlock] VideoID recorded: " + recordedVideoID + ". Actual VideoID: " + currentVideoID);
console.error("[SponsorBlock] SponsorTime", sponsorTime, "sponsorTimes", sponsorTimes, "sponsorTimesSubmitting", sponsorTimesSubmitting);
// Video ID change occured
checkVideoIDChange();
@@ -818,6 +819,8 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
}
}
let playbackRateCheckInterval: NodeJS.Timeout | null = null;
let lastPlaybackSpeed = 1;
let setupVideoListenersFirstTime = true;
function setupVideoListeners() {
//wait until it is loaded
@@ -837,6 +840,16 @@ function setupVideoListeners() {
let startedWaiting = false;
let lastPausedAtZero = true;
const rateChangeListener = () => {
updateVirtualTime();
clearWaitingTime();
startSponsorSchedule();
};
getVideo().addEventListener('ratechange', rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
const playListener = () => {
// If it is not the first event, then the only way to get to 0 is if there is a seek event
// This check makes sure that changing the video resolution doesn't cause the extension to think it
@@ -867,7 +880,6 @@ function setupVideoListeners() {
startSponsorSchedule();
}
};
getVideo().addEventListener('play', playListener);
@@ -897,6 +909,27 @@ function setupVideoListeners() {
startSponsorSchedule();
}
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastPlaybackSpeed = getVideo().playbackRate;
// Video speed controller compatibility
// That extension makes rate change events not propagate
if (document.body.classList.contains("vsc-initialized")) {
playbackRateCheckInterval = setInterval(() => {
if ((!getVideoID() || getVideo().paused) && playbackRateCheckInterval) {
// Video is gone, stop checking
clearInterval(playbackRateCheckInterval);
return;
}
if (getVideo().playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = getVideo().playbackRate;
rateChangeListener();
}
}, 2000);
}
};
getVideo().addEventListener('playing', playingListener);
@@ -927,21 +960,13 @@ function setupVideoListeners() {
};
getVideo().addEventListener('seeking', seekingListener);
const rateChangeListener = () => {
updateVirtualTime();
clearWaitingTime();
startSponsorSchedule();
};
getVideo().addEventListener('ratechange', () => rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
const stoppedPlayback = () => {
// Reset lastCheckVideoTime
lastCheckVideoTime = -1;
lastCheckTime = 0;
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastKnownVideoTime.videoTime = null;
lastKnownVideoTime.preciseTime = null;
updateWaitingTime();
@@ -973,6 +998,8 @@ function setupVideoListeners() {
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener);
getVideo().removeEventListener('pause', pauseListener);
getVideo().removeEventListener('waiting', waitingListener);
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
});
}
}

View File

@@ -1,3 +1,3 @@
import { init } from "./maze-utils/injected/document";
import { init } from "../maze-utils/src/injected/document";
init();

View File

@@ -1,8 +1,8 @@
import { localizeHtmlPage } from "./maze-utils/setup";
import { localizeHtmlPage } from "../maze-utils/src/setup";
import Config from "./config";
import { showDonationLink } from "./utils/configUtils";
import { waitFor } from "./maze-utils";
import { waitFor } from "../maze-utils/src";
if (document.readyState === "complete") {
init();

View File

@@ -11,9 +11,9 @@ import { ActionType, Category, SegmentContainer, SponsorHideType, SponsorSourceT
import { partition } from "../utils/arrayUtils";
import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
import { normalizeChapterName } from "../utils/exporter";
import { getFormattedTimeToSeconds } from "../maze-utils/formating";
import { findValidElement } from "../maze-utils/dom";
import { addCleanupListener } from "../maze-utils/cleanup";
import { getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
import { findValidElement } from "../../maze-utils/src/dom";
import { addCleanupListener } from "../../maze-utils/src/cleanup";
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
const MIN_CHAPTER_SIZE = 0.003;
@@ -784,11 +784,13 @@ class PreviewBar {
if (!Config.config.showSegmentNameInChapterBar
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
const chaptersContainer = this.getChaptersContainer();
chaptersContainer.querySelector(".sponsorChapterText")?.remove();
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
chapterTitle.style.removeProperty("display");
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
if (chaptersContainer) {
chaptersContainer.querySelector(".sponsorChapterText")?.remove();
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
chapterTitle.style.removeProperty("display");
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
}
return [];
}

View File

@@ -2,7 +2,7 @@ import Config from "../config";
import { SponsorTime } from "../types";
import { getSkippingText } from "../utils/categoryUtils";
import { AnimationUtils } from "../utils/animationUtils";
import { keybindToString } from "../maze-utils/config";
import { keybindToString } from "../../maze-utils/src/config";
export interface SkipButtonControlBarProps {
skip: (segment: SponsorTime) => void;

View File

@@ -1 +0,0 @@
../maze-utils/src/

View File

@@ -13,10 +13,10 @@ import CategoryChooser from "./render/CategoryChooser";
import UnsubmittedVideos from "./render/UnsubmittedVideos";
import KeybindComponent from "./components/options/KeybindComponent";
import { showDonationLink } from "./utils/configUtils";
import { localizeHtmlPage } from "./maze-utils/setup";
import { StorageChangesObject } from "./maze-utils/config";
import { getHash } from "./maze-utils/hash";
import { isFirefoxOrSafari } from "./maze-utils";
import { localizeHtmlPage } from "../maze-utils/src/setup";
import { StorageChangesObject } from "../maze-utils/src/config";
import { getHash } from "../maze-utils/src/hash";
import { isFirefoxOrSafari } from "../maze-utils/src";
import { isDeArrowInstalled } from "./utils/crossExtension";
const utils = new Utils();
let embed = false;

View File

@@ -1,6 +1,6 @@
import Config from "./config";
import Utils from "./utils";
import { localizeHtmlPage } from "./maze-utils/setup";
import { localizeHtmlPage } from "../maze-utils/src/setup";
const utils = new Utils();
// This is needed, if Config is not imported before Utils, things break.

View File

@@ -21,12 +21,12 @@ import {
import { showDonationLink } from "./utils/configUtils";
import { AnimationUtils } from "./utils/animationUtils";
import { shortCategoryName } from "./utils/categoryUtils";
import { localizeHtmlPage } from "./maze-utils/setup";
import { localizeHtmlPage } from "../maze-utils/src/setup";
import { exportTimes } from "./utils/exporter";
import GenericNotice from "./render/GenericNotice";
import { getErrorMessage, getFormattedTime } from "./maze-utils/formating";
import { StorageChangesObject } from "./maze-utils/config";
import { getHash } from "./maze-utils/hash";
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
import { StorageChangesObject } from "../maze-utils/src/config";
import { getHash } from "../maze-utils/src/hash";
const utils = new Utils();

View File

@@ -5,9 +5,9 @@ import Config from "../config";
import { VoteResponse } from "../messageTypes";
import { Category, SegmentUUID, SponsorTime } from "../types";
import { Tooltip } from "./Tooltip";
import { waitFor } from "../maze-utils";
import { getYouTubeTitleNode } from "../maze-utils/elements";
import { addCleanupListener } from "../maze-utils/cleanup";
import { waitFor } from "../../maze-utils/src";
import { getYouTubeTitleNode } from "../../maze-utils/src/elements";
import { addCleanupListener } from "../../maze-utils/src/cleanup";
const id = "categoryPill";

View File

@@ -99,8 +99,8 @@ export interface Registration {
message: string;
id: string;
allFrames: boolean;
js: browser.extensionTypes.ExtensionFileOrCode[];
css: browser.extensionTypes.ExtensionFileOrCode[];
js: string[];
css: string[];
matches: string[];
}

View File

@@ -1,12 +1,12 @@
import Config, { VideoDownvotes } from "./config";
import { CategorySelection, SponsorTime, BackgroundScriptContainer, Registration, VideoID, SponsorHideType, CategorySkipOption } from "./types";
import { getHash, HashedValue } from "./maze-utils/hash";
import { getHash, HashedValue } from "../maze-utils/src/hash";
import * as CompileConfig from "../config.json";
import { isFirefoxOrSafari, waitFor } from "./maze-utils";
import { findValidElementFromSelector } from "./maze-utils/dom";
import { FetchResponse, sendRequestToCustomServer } from "./maze-utils/background-request-proxy"
import { isSafari } from "./maze-utils/config";
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
import { findValidElementFromSelector } from "../maze-utils/src/dom";
import { FetchResponse, sendRequestToCustomServer } from "../maze-utils/src/background-request-proxy"
import { isSafari } from "../maze-utils/src/config";
export default class Utils {
@@ -47,9 +47,13 @@ export default class Utils {
* @param {CallableFunction} callback
*/
setupExtraSitePermissions(callback: (granted: boolean) => void): void {
let permissions = ["webNavigation"];
if (!isSafari()) permissions.push("declarativeContent");
if (isFirefoxOrSafari() && !isSafari()) permissions = [];
const permissions = [];
if (!isFirefoxOrSafari()) {
permissions.push("declarativeContent");
}
if (!isFirefoxOrSafari() || isSafari()) {
permissions.push("webNavigation");
}
chrome.permissions.request({
origins: this.getPermissionRegex(),
@@ -73,21 +77,12 @@ export default class Utils {
* For now, it is just SB.config.invidiousInstances.
*/
setupExtraSiteContentScripts(): void {
const firefoxJS = [];
for (const file of this.js) {
firefoxJS.push({file});
}
const firefoxCSS = [];
for (const file of this.css) {
firefoxCSS.push({file});
}
const registration: Registration = {
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
js: this.js,
css: this.css,
matches: this.getPermissionRegex()
};

View File

@@ -1,8 +1,8 @@
import * as CompileConfig from "../../config.json";
import Config from "../config";
import { isSafari } from "../maze-utils/config";
import { isFirefoxOrSafari } from "../maze-utils";
import { isSafari } from "../../maze-utils/src/config";
import { isFirefoxOrSafari } from "../../maze-utils/src";
export function isDeArrowInstalled(): Promise<boolean> {
if (Config.config.deArrowInstalled) {

View File

@@ -1,8 +1,8 @@
import { ActionType, Category, SegmentUUID, SponsorSourceType, SponsorTime } from "../types";
import { shortCategoryName } from "./categoryUtils";
import * as CompileConfig from "../../config.json";
import { getFormattedTime, getFormattedTimeToSeconds } from "../maze-utils/formating";
import { generateUserID } from "../maze-utils/setup";
import { getFormattedTime, getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
import { generateUserID } from "../../maze-utils/src/setup";
const inTest = typeof chrome === "undefined";

View File

@@ -1,5 +1,5 @@
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
import { getFormattedTimeToSeconds } from "../maze-utils/formating";
import { getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
export function getControls(): HTMLElement {
const controlsSelectors = [

View File

@@ -1,7 +1,7 @@
import { isOnInvidious, parseYouTubeVideoIDFromURL } from "../maze-utils/video";
import { isOnInvidious, parseYouTubeVideoIDFromURL } from "../../maze-utils/src/video";
import Config from "../config";
import { getVideoLabel } from "./videoLabels";
import { setThumbnailListener } from "../maze-utils/thumbnailManagement";
import { setThumbnailListener } from "../../maze-utils/src/thumbnailManagement";
export async function labelThumbnails(thumbnails: HTMLImageElement[]): Promise<void> {
await Promise.all(thumbnails.map((t) => labelThumbnail(t)));

View File

@@ -1,5 +1,5 @@
import { Category, CategorySkipOption, VideoID } from "../types";
import { getHash } from "../maze-utils/hash";
import { getHash } from "../../maze-utils/src/hash";
import Utils from "../utils";
import { logWarn } from "./logger";

View File

@@ -1,5 +1,5 @@
import { objectToURI } from "../maze-utils";
import { getHash } from "../maze-utils/hash";
import { objectToURI } from "../../maze-utils/src";
import { getHash } from "../../maze-utils/src/hash";
import Config from "../config";
import GenericNotice, { NoticeOptions } from "../render/GenericNotice";
import { ContentContainer } from "../types";