Compare commits

...

17 Commits
5.5 ... 5.5.3

Author SHA1 Message Date
Ajay
88dc8db6e7 bump version 2024-01-23 14:27:05 -05:00
Ajay
c69a574379 update translations 2024-01-23 14:27:01 -05:00
Ajay
516d624f16 Don't require preview for segments ending at end of the video
Fixes #1959
2024-01-23 14:25:07 -05:00
Ajay
a662c3e04f Reloading after creating segments shouldn't require previewing 2024-01-23 14:22:54 -05:00
Ajay
985910cbf6 Count previewed unsubmitted segments previewed manually 2024-01-23 14:20:24 -05:00
Ajay
feae86f6ea Don't throw errors on extension live-update 2024-01-21 20:42:40 -05:00
Ajay
1f96e3b117 Improve precision of hover preview
Also fixes issue with YouTube "most-replayed" messing it up
2024-01-21 20:35:00 -05:00
Ajay
b3b5d46e4e bump version 2024-01-21 15:57:35 -05:00
Ajay
c996680a58 Fix category selection changes not saving 2024-01-21 15:57:22 -05:00
Ajay
ade4654ae0 bump version 2024-01-21 14:26:27 -05:00
Ajay
4e9e6282f6 update translations 2024-01-21 14:26:16 -05:00
Ajay
783326afca Use runtime.getURL 2024-01-21 13:51:32 -05:00
Ajay
8dfd06919b Only require a preview for skip and mute segments 2024-01-21 13:40:01 -05:00
Ajay
50ee690717 Only prevent scrolling while editing 2024-01-21 13:37:29 -05:00
Ajay
74aebd32a7 Prevent zooming when trying to scroll to edit times 2024-01-21 13:31:45 -05:00
Ajay
e489d0f913 Fix german title not being shortened 2024-01-16 18:39:29 -05:00
Ajay
814df46521 Don't warn about using the word intro in chapter names 2024-01-16 18:21:44 -05:00
12 changed files with 75 additions and 69 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "SponsorBlock",
"version": "5.5",
"version": "5.5.3",
"default_locale": "en",
"description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app",

View File

@@ -123,7 +123,7 @@ chrome.runtime.onInstalled.addListener(function () {
// If there is no userID, then it is the first install.
if (!userID && !Config.local.alreadyInstalled){
//open up the install page
chrome.tabs.create({url: chrome.extension.getURL("/help/index.html")});
chrome.tabs.create({url: chrome.runtime.getURL("/help/index.html")});
//generate a userID
const newUserID = generateUserID();
@@ -137,7 +137,7 @@ chrome.runtime.onInstalled.addListener(function () {
if (Config.config.supportInvidious) {
if (!(await utils.containsInvidiousPermission())) {
chrome.tabs.create({url: chrome.extension.getURL("/permissions/index.html")});
chrome.tabs.create({url: chrome.runtime.getURL("/permissions/index.html")});
}
}
}, 1500);

View File

@@ -53,7 +53,7 @@ class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryP
<span className="sponsorBlockCategoryPillTitleSection">
<img className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
src={chrome.runtime.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
{
@@ -86,7 +86,7 @@ class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryP
)}
{/* Close Button */}
<img src={chrome.extension.getURL("icons/close.png")}
<img src={chrome.runtime.getURL("icons/close.png")}
className="categoryPillClose"
onClick={() => {
this.setState({ show: false });

View File

@@ -207,7 +207,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
{/* Close button */}
<img src={chrome.extension.getURL("icons/close.png")}
<img src={chrome.runtime.getURL("icons/close.png")}
className={"sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeCloseButton sponsorSkipNoticeRightButton"
+ (this.props.biggerCloseButton ? " biggerCloseButton" : "")}
onClick={() => this.close()}>

View File

@@ -34,7 +34,7 @@ export interface SponsorTimeEditState {
chapterNameSelectorHovering: boolean;
}
const categoryNamesGrams: string[] = [].concat(...CompileConfig.categoryList.filter((name) => name !== "chapter")
const categoryNamesGrams: string[] = [].concat(...CompileConfig.categoryList.filter((name) => !["chapter", "intro"].includes(name))
.map((name) => chrome.i18n.getMessage("category_" + name).split(/\/|\s|-/)));
class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, SponsorTimeEditState> {
@@ -81,13 +81,15 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
componentDidMount(): void {
// Prevent inputs from triggering key events
document.getElementById("sponsorTimeEditContainer" + this.idSuffix).addEventListener('keydown', function (event) {
event.stopPropagation();
document.getElementById("sponsorTimeEditContainer" + this.idSuffix).addEventListener('keydown', (e) => {
e.stopPropagation();
});
// Prevent scrolling while changing times
document.getElementById("sponsorTimesContainer" + this.idSuffix).addEventListener('wheel', function (event) {
event.preventDefault();
document.getElementById("sponsorTimesContainer" + this.idSuffix).addEventListener('wheel', (e) => {
if (this.state.editing) {
e.preventDefault();
}
}, {passive: false});
// Add as a config listener
@@ -221,7 +223,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
target="_blank" rel="noreferrer">
<img id={"sponsorTimeCategoriesHelpButton" + this.idSuffix}
className="helpButton"
src={chrome.extension.getURL("icons/help.svg")}
src={chrome.runtime.getURL("icons/help.svg")}
title={chrome.i18n.getMessage("categoryGuidelines")} />
</a>
</div>

View File

@@ -69,6 +69,13 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
this.videoObserver.observe(this.contentContainer().v, {
attributes: true
});
// Prevent zooming while changing times
document.getElementById("sponsorSkipNoticeMiddleRow" + this.state.idSuffix).addEventListener('wheel', function (event) {
if (event.ctrlKey) {
event.preventDefault();
}
}, {passive: false});
}
componentWillUnmount(): void {
@@ -100,7 +107,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
onClick={() => this.sortSegments()}
title={chrome.i18n.getMessage("sortSegments")}
key="sortButton"
src={chrome.extension.getURL("icons/sort.svg")}>
src={chrome.runtime.getURL("icons/sort.svg")}>
</img>;
const exportButton =
<img id={"sponsorSkipExportButton" + this.state.idSuffix}
@@ -108,7 +115,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
onClick={() => this.exportSegments()}
title={chrome.i18n.getMessage("exportSegments")}
key="exportButton"
src={chrome.extension.getURL("icons/export.svg")}>
src={chrome.runtime.getURL("icons/export.svg")}>
</img>;
return (
<NoticeComponent noticeTitle={this.state.noticeTitle}

View File

@@ -158,7 +158,7 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
});
}
Config.forceLocalUpdate("categorySelections");
Config.forceSyncUpdate("categorySelections");
}
getCategorySkipOptions(): JSX.Element[] {

View File

@@ -1608,6 +1608,9 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
}
if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
} else if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
// Count that as a previewed segment
previewedSegment = true;
}
}
}
@@ -1768,7 +1771,7 @@ function createButton(baseID: string, title: string, callback: () => void, image
newButton.draggable = isDraggable;
newButtonImage.id = baseID + "Image";
newButtonImage.className = "playerButtonImage";
newButtonImage.src = chrome.extension.getURL("icons/" + imageName);
newButtonImage.src = chrome.runtime.getURL("icons/" + imageName);
// Append image to button
newButton.appendChild(newButtonImage);
@@ -1867,10 +1870,10 @@ function updateEditButtonsOnPlayer(): void {
if (buttonsEnabled) {
if (creatingSegment) {
playerButtons.startSegment.image.src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker.svg");
playerButtons.startSegment.image.src = chrome.runtime.getURL("icons/PlayerStopIconSponsorBlocker.svg");
playerButtons.startSegment.button.setAttribute("title", chrome.i18n.getMessage("sponsorEnd"));
} else {
playerButtons.startSegment.image.src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker.svg");
playerButtons.startSegment.image.src = chrome.runtime.getURL("icons/PlayerStartIconSponsorBlocker.svg");
playerButtons.startSegment.button.setAttribute("title", chrome.i18n.getMessage("sponsorStart"));
}
}
@@ -1983,6 +1986,9 @@ function updateSponsorTimesSubmitting(getFromConfig = true) {
}
if (sponsorTimesSubmitting.length > 0) {
// Assume they already previewed a segment
previewedSegment = true;
importExistingChapters(true);
}
}
@@ -2048,7 +2054,7 @@ function openInfoMenu() {
}
}
});
frame.src = chrome.extension.getURL("popup.html");
frame.src = chrome.runtime.getURL("popup.html");
popup.appendChild(frame);
const elemHasChild = (elements: NodeListOf<HTMLElement>): Element => {
@@ -2266,13 +2272,16 @@ async function sendSubmitMessage() {
return;
}
if (!previewedSegment) {
if (!previewedSegment
&& !sponsorTimesSubmitting.every((segment) =>
[ActionType.Full, ActionType.Chapter, ActionType.Poi].includes(segment.actionType)
|| segment.segment[1] >= getVideo()?.duration)) {
alert(`${chrome.i18n.getMessage("previewSegmentRequired")} ${keybindToString(Config.config.previewKeybind)}`);
return;
}
// Add loading animation
playerButtons.submit.image.src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker.svg");
playerButtons.submit.image.src = chrome.runtime.getURL("icons/PlayerUploadIconSponsorBlocker.svg");
const stopAnimation = AnimationUtils.applyLoadingAnimation(playerButtons.submit.button, 1, () => updateEditButtonsOnPlayer());
//check if a sponsor exceeds the duration of the video
@@ -2347,7 +2356,7 @@ async function sendSubmitMessage() {
} else {
// Show that the upload failed
playerButtons.submit.button.style.animation = "unset";
playerButtons.submit.image.src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker.svg");
playerButtons.submit.image.src = chrome.runtime.getURL("icons/PlayerUploadFailedIconSponsorBlocker.svg");
if (response.status === 403 && response.responseText.startsWith("Submission rejected due to a tip from a moderator.")) {
openWarningDialog(skipNoticeContentContainer);
@@ -2531,7 +2540,7 @@ function addCSS() {
fileref.rel = "stylesheet";
fileref.type = "text/css";
fileref.href = chrome.extension.getURL(file);
fileref.href = chrome.runtime.getURL(file);
head.appendChild(fileref);
}

View File

@@ -11,7 +11,6 @@ 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/src/formating";
import { findValidElement } from "../../maze-utils/src/dom";
import { addCleanupListener } from "../../maze-utils/src/cleanup";
@@ -125,34 +124,11 @@ class PreviewBar {
mouseOnSeekBar = false;
});
const observer = new MutationObserver((mutations) => {
if (!mouseOnSeekBar || !this.categoryTooltip || !this.categoryTooltipContainer) return;
seekBar.addEventListener("mousemove", (e: MouseEvent) => {
if (!mouseOnSeekBar || !this.categoryTooltip || !this.categoryTooltipContainer || !chrome.runtime?.id) return;
// Only care about mutations to time tooltip
if (!mutations.some((mutation) => (mutation.target as HTMLElement).classList.contains("ytp-tooltip-text"))) {
return;
}
const tooltipTextElements = tooltipTextWrapper.querySelectorAll(".ytp-tooltip-text");
let timeInSeconds: number | null = null;
let noYoutubeChapters = false;
for (const tooltipTextElement of tooltipTextElements) {
if (tooltipTextElement.classList.contains('ytp-tooltip-text-no-title')) noYoutubeChapters = true;
const tooltipText = tooltipTextElement.textContent;
if (tooltipText === null || tooltipText.length === 0) continue;
timeInSeconds = getFormattedTimeToSeconds(tooltipText);
if (timeInSeconds !== null) break;
}
if (timeInSeconds === null) {
originalTooltip.style.removeProperty("display");
return;
}
let noYoutubeChapters = !!tooltipTextWrapper.querySelector(".ytp-tooltip-text.ytp-tooltip-text-no-title");
const timeInSeconds = this.decimalToTime((e.clientX - seekBar.getBoundingClientRect().x) / seekBar.clientWidth);
// Find the segment at that location, using the shortest if multiple found
const [normalSegments, chapterSegments] =
@@ -198,15 +174,6 @@ class PreviewBar {
this.chapterTooltip.style.textAlign = titleTooltip.style.textAlign;
}
});
observer.observe(tooltipTextWrapper, {
childList: true,
subtree: true,
});
addCleanupListener(() => {
observer.disconnect();
});
}
private setTooltipTitle(segment: PreviewBarSegment, tooltip: HTMLElement): void {
@@ -920,6 +887,17 @@ class PreviewBar {
}
timeToDecimal(time: number): number {
return this.decimalTimeConverter(time, true);
}
decimalToTime(decimal: number): number {
return this.decimalTimeConverter(decimal, false);
}
/**
* Decimal to time or time to decimal
*/
decimalTimeConverter(value: number, isTime: boolean): number {
if (this.originalChapterBarBlocks?.length > 1 && this.existingChapters.length === this.originalChapterBarBlocks?.length) {
// Parent element to still work when display: none
const totalPixels = this.originalChapterBar.parentElement.clientWidth;
@@ -929,8 +907,9 @@ class PreviewBar {
const chapterElement = this.originalChapterBarBlocks[i];
const widthPixels = parseFloat(chapterElement.style.width.replace("px", ""));
if (time >= this.existingChapters[i].segment[1]) {
const marginPixels = chapterElement.style.marginRight ? parseFloat(chapterElement.style.marginRight.replace("px", "")) : 0;
const marginPixels = chapterElement.style.marginRight ? parseFloat(chapterElement.style.marginRight.replace("px", "")) : 0;
if ((isTime && value >= this.existingChapters[i].segment[1])
|| (!isTime && value >= (pixelOffset + widthPixels + marginPixels) / totalPixels)) {
pixelOffset += widthPixels + marginPixels;
lastCheckedChapter = i;
} else {
@@ -944,13 +923,22 @@ class PreviewBar {
const latestWidth = parseFloat(this.originalChapterBarBlocks[lastCheckedChapter + 1].style.width.replace("px", ""));
const latestChapterDuration = latestChapter.segment[1] - latestChapter.segment[0];
const percentageInCurrentChapter = (time - latestChapter.segment[0]) / latestChapterDuration;
const sizeOfCurrentChapter = latestWidth / totalPixels;
return Math.min(1, ((pixelOffset / totalPixels) + (percentageInCurrentChapter * sizeOfCurrentChapter)));
if (isTime) {
const percentageInCurrentChapter = (value - latestChapter.segment[0]) / latestChapterDuration;
const sizeOfCurrentChapter = latestWidth / totalPixels;
return Math.min(1, ((pixelOffset / totalPixels) + (percentageInCurrentChapter * sizeOfCurrentChapter)));
} else {
const percentageInCurrentChapter = (value * totalPixels - pixelOffset) / latestWidth;
return Math.max(0, latestChapter.segment[0] + (percentageInCurrentChapter * latestChapterDuration));
}
}
}
return Math.min(1, time / this.videoDuration);
if (isTime) {
return Math.min(1, value / this.videoDuration);
} else {
return Math.max(0, value * this.videoDuration);
}
}
/*

View File

@@ -59,7 +59,7 @@ export class RectangleTooltip {
className="sponsorBlockRectangleTooltip" >
<div>
<img className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
src={chrome.runtime.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
<span className="sponsorSkipObject">
{this.text + (props.link ? ". " : "")}

View File

@@ -160,7 +160,7 @@ module.exports = env => {
if (path.match(/(\/|\\)_locales(\/|\\).+/)) {
const parsed = JSON.parse(content.toString());
if (env.browser.toLowerCase() === "safari") {
parsed.fullName.message = parsed.fullName.message.match(/^.+(?= -)/)?.[0] || parsed.fullName.message;
parsed.fullName.message = parsed.fullName.message.match(/^.+(?= [-])/)?.[0] || parsed.fullName.message;
if (parsed.fullName.message.length > 50) {
parsed.fullName.message = parsed.fullName.message.slice(0, 47) + "...";
}