Compare commits

...

15 Commits
5.5.9 ... 5.6

Author SHA1 Message Date
Ajay
15fcc971f6 bump version 2024-05-24 03:26:02 -04:00
Ajay
32adbb9581 update translations 2024-05-24 03:22:36 -04:00
Ajay
4ecd02510b Fix warnings 2024-05-24 03:22:07 -04:00
Ajay
0dbb6474b8 Fix preview bar on mobile
Fixes #2021
2024-05-24 03:20:21 -04:00
Ajay
c974c2a6d6 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2024-05-24 03:15:59 -04:00
Ajay
a6695254b6 Fix skipping and preview bar on "add to queue", miniplayer and hover preview
Fixes #1486
2024-05-24 03:15:58 -04:00
Ajay
e8a82eddca Change chapters sorting 2024-05-09 19:09:37 -04:00
Ajay Ramachandran
d3684dbedd Merge pull request #2017 from stdedos/fix/disabled-comment-typo
Fix comment typo
2024-05-08 17:54:10 -04:00
Stavros Ntentos
6c9a403731 Fix comment typo
Signed-off-by: Stavros Ntentos <133706+stdedos@users.noreply.github.com>
2024-05-08 23:44:01 +03:00
Ajay
3be51c89a9 Fix popup sometimes saying "No video found"
Fixes #2006
Fixes #2013
Fixes #1999
2024-04-30 20:54:54 -04:00
Ajay
5b845a56e1 Fix unsubmitted segments sometimes manual skipping if manual skip enabled for category
Fixes #2002
2024-04-28 22:59:02 -04:00
Ajay
7b572c3c0e Fix previewed segment check
Fixes #1996
2024-04-28 21:51:35 -04:00
Ajay
56bb22d03d Allow importing segments with no category
Also fixes case when importing chapters when having no permission to submit chapters
2024-04-26 16:44:20 -04:00
Ajay
e1d656f43f Make notice visibility option not appear when notice disabled 2024-04-04 13:54:47 -04:00
Ajay
e14b3c76f9 Improve submission box padding 2024-03-27 16:14:10 -04:00
11 changed files with 239 additions and 163 deletions

View File

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

View File

@@ -26,6 +26,11 @@
transition: transform .1s cubic-bezier(0,0,0.2,1);
}
/* May 2024 hover preview */
.YtPlayerProgressBarProgressBar #previewbar {
transform: none;
}
.ytp-big-mode #previewbar {
transform: scaleY(0.625) translateY(-30%) translateY(1.5px);
}

View File

@@ -219,20 +219,22 @@
__MSG_showSkipNotice__
</label>
</div>
<div data-type="selector" data-sync="noticeVisibilityMode" data-dependent-on="dontShowNotice">
<br/>
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
<option value="0">__MSG_noticeVisibilityMode0__</option>
<option value="1">__MSG_noticeVisibilityMode1__</option>
<option value="2">__MSG_noticeVisibilityMode2__</option>
<option value="3">__MSG_noticeVisibilityMode3__</option>
<option value="4">__MSG_noticeVisibilityMode4__</option>
</select>
</div>
</div>
<div data-type="selector" data-sync="noticeVisibilityMode">
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
<option value="0">__MSG_noticeVisibilityMode0__</option>
<option value="1">__MSG_noticeVisibilityMode1__</option>
<option value="2">__MSG_noticeVisibilityMode2__</option>
<option value="3">__MSG_noticeVisibilityMode3__</option>
<option value="4">__MSG_noticeVisibilityMode4__</option>
</select>
</div>
<div data-type="toggle" data-sync="showCategoryGuidelines">
<div class="switch-container">
<label class="switch">

View File

@@ -272,48 +272,49 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
</div>
): ""}
<br/>
{/* Editing Tools */}
<span id={"sponsorTimeDeleteButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.deleteTime.bind(this)}>
{chrome.i18n.getMessage("delete")}
</span>
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
&& this.state.selectedActionType !== ActionType.Chapter ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix}
<div style={{ marginTop: "3px" }}>
<span id={"sponsorTimeDeleteButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
{chrome.i18n.getMessage("preview")}
onClick={this.deleteTime.bind(this)}>
{chrome.i18n.getMessage("delete")}
</span>
): ""}
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeInspectButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.inspectTime.bind(this)}>
{chrome.i18n.getMessage("inspect")}
</span>
): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
&& this.state.selectedActionType !== ActionType.Chapter ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
{chrome.i18n.getMessage("preview")}
</span>
): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? (
<span id={"sponsorTimePreviewEndButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
{chrome.i18n.getMessage("End")}
</span>
): ""}
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeInspectButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.inspectTime.bind(this)}>
{chrome.i18n.getMessage("inspect")}
</span>
): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? (
<span id={"sponsorTimePreviewEndButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
{chrome.i18n.getMessage("End")}
</span>
): ""}
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeEditButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.toggleEditTime.bind(this)}>
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
</span>
): ""}
</div>
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeEditButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.toggleEditTime.bind(this)}>
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
</span>
): ""}
</div>
);
}

View File

@@ -140,7 +140,7 @@ interface SBStorage {
downvotedSegments: Record<VideoID & HashedValue, VideoDownvotes>;
navigationApiAvailable: boolean;
// Used when sync storage disbaled
// Used when sync storage disabled
alreadyInstalled: boolean;
/* Contains unsubmitted segments that the user has created. */

View File

@@ -34,7 +34,7 @@ import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings";
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 { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube, getLastNonInlineVideoID, triggerVideoIDChange, triggerVideoElementChange, getIsInline } from "../maze-utils/src/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
import { findValidElement } from "../maze-utils/src/dom"
import { getHash, HashedValue } from "../maze-utils/src/hash";
@@ -49,6 +49,7 @@ import { hideDeArrowPromotion, tryShowingDeArrowPromotion } from "./dearrowPromo
import { asyncRequestToServer } from "./utils/requests";
import { isMobileControlsOpen } from "./utils/mobileUtils";
import { defaultPreviewTime } from "./utils/constants";
import { onVideoPage } from "../maze-utils/src/pageInfo";
cleanPage();
@@ -72,6 +73,8 @@ let sponsorDataFound = false;
let sponsorTimes: SponsorTime[] = [];
let existingChaptersImported = false;
let importingChaptersWaitingForFocus = false;
let importingChaptersWaiting = false;
let triedImportingChapters = false;
// List of open skip notices
const skipNotices: SkipNotice[] = [];
let activeSkipKeybindElement: ToggleSkippable = null;
@@ -128,9 +131,6 @@ setupVideoModule({
}, () => Config);
setupThumbnailListener();
//the video id of the last preview bar update
let lastPreviewBarUpdate: VideoID;
// Is the video currently being switched
let switchingVideos = null;
@@ -168,7 +168,6 @@ let submissionNotice: SubmissionNotice = null;
let lastResponseStatus: number;
let retryCount = 0;
let lookupWaiting = false;
// Contains all of the functions and variables needed by the skip notice
const skipNoticeContentContainer: ContentContainer = () => ({
@@ -219,7 +218,7 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
found: sponsorDataFound,
status: lastResponseStatus,
sponsorTimes: sponsorTimes,
time: getVideo().currentTime,
time: getVideo()?.currentTime ?? 0,
onMobileYouTube: isOnMobileYouTube()
});
@@ -303,7 +302,9 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
if (!sponsorTimesSubmitting.some(
(s) => Math.abs(s.segment[0] - segment.segment[0]) < 1
&& Math.abs(s.segment[1] - segment.segment[1]) < 1)) {
if (segment.category === "chapter" && !utils.getCategorySelection("chapter")) {
const hasChaptersPermission = (Config.config.showCategoryWithoutPermission
|| Config.config.permissions["chapter"]);
if (segment.category === "chapter" && (!utils.getCategorySelection("chapter") || !hasChaptersPermission)) {
segment.category = "chooseACategory" as Category;
segment.actionType = ActionType.Skip;
segment.description = "";
@@ -382,6 +383,7 @@ function resetValues() {
sponsorTimes = [];
existingChaptersImported = false;
triedImportingChapters = false;
sponsorSkipped = [];
lastResponseStatus = 0;
shownSegmentFailedToFetchWarning = false;
@@ -398,8 +400,9 @@ function resetValues() {
//reset sponsor data found check
sponsorDataFound = false;
if (switchingVideos === null) {
// When first loading a video, it is not switching videos
// When first loading a video, it is not switching videos
// Hover play also doesn't need this check
if (switchingVideos === null || !onVideoPage()) {
switchingVideos = false;
} else {
switchingVideos = true;
@@ -456,6 +459,17 @@ function videoIDChange(): void {
updateSponsorTimesSubmitting();
tryShowingDeArrowPromotion().catch(logWarn);
checkPreviewbarState();
if (getIsInline()) {
// Hover preview progress bar can take some time to appear
// and if the miniplayer is also active then it would
// attach to the wrong one
setTimeout(checkPreviewbarState, 500);
setTimeout(checkPreviewbarState, 1000);
setTimeout(checkPreviewbarState, 3000);
}
}
function handleMobileControlsMutations(): void {
@@ -484,12 +498,7 @@ function handleMobileControlsMutations(): void {
createPreviewBar();
}
/**
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
function getPreviewBarAttachElement(): HTMLElement | null {
const progressElementOptions = [{
// For new mobile YouTube (#1287)
selector: ".progress-bar-line",
@@ -499,11 +508,22 @@ function createPreviewBar(): void {
selector: ".YtProgressBarProgressBarLine",
isVisibleCheck: true
}, {
// For Desktop YouTube
// For newer mobile YouTube (May 2024)
selector: ".YtmProgressBarProgressBarLine",
isVisibleCheck: true
}, {
// For desktop YouTube hover play
// Priority is given to the hover play progress bar over the main progress bar
// for miniplayer + hover preview case
// Second is new hover play selector
selector: "#video-preview .ytp-progress-bar, #video-preview .YtProgressBarLineHost",
isVisibleCheck: true
}, {
// For desktop YouTube
selector: ".ytp-progress-bar",
isVisibleCheck: true
}, {
// For Desktop YouTube
// For desktop YouTube
selector: ".no-model.cue-range-marker",
isVisibleCheck: true
}, {
@@ -526,14 +546,27 @@ function createPreviewBar(): void {
const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0];
if (el) {
const chapterVote = new ChapterVote(voteAsync);
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
updatePreviewBar();
break;
return el;
}
}
return null;
}
/**
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const el = getPreviewBarAttachElement();
if (el) {
const chapterVote = new ChapterVote(voteAsync);
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
updatePreviewBar();
}
}
/**
@@ -787,6 +820,8 @@ function inMuteSegment(currentTime: number, includeOverlap: boolean): boolean {
* This makes sure the videoID is still correct and if the sponsorTime is included
*/
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
if (!onVideoPage()) return false;
const currentVideoID = getYouTubeVideoID();
const recordedVideoID = videoID || getVideoID();
if (currentVideoID !== recordedVideoID || (sponsorTime
@@ -810,14 +845,16 @@ let playbackRateCheckInterval: NodeJS.Timeout | null = null;
let lastPlaybackSpeed = 1;
let setupVideoListenersFirstTime = true;
function setupVideoListeners() {
const video = getVideo();
//wait until it is loaded
getVideo().addEventListener('loadstart', videoOnReadyListener)
getVideo().addEventListener('durationchange', durationChangeListener);
video.addEventListener('loadstart', videoOnReadyListener)
video.addEventListener('durationchange', durationChangeListener);
if (setupVideoListenersFirstTime) {
addCleanupListener(() => {
getVideo().removeEventListener('loadstart', videoOnReadyListener);
getVideo().removeEventListener('durationchange', durationChangeListener);
video.removeEventListener('loadstart', videoOnReadyListener);
video.removeEventListener('durationchange', durationChangeListener);
});
}
@@ -833,18 +870,20 @@ function setupVideoListeners() {
startSponsorSchedule();
};
getVideo().addEventListener('ratechange', rateChangeListener);
video.addEventListener('ratechange', rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
video.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
// gone back to the begining
if (getVideo().readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
&& getVideo().currentTime === 0) return;
if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
&& video.currentTime === 0) return;
updateVirtualTime();
checkForMiniplayerPlaying();
if (switchingVideos || lastPausedAtZero) {
switchingVideos = false;
@@ -860,15 +899,15 @@ function setupVideoListeners() {
updateAdFlag();
// Make sure it doesn't get double called with the playing event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) {
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime;
lastCheckVideoTime = video.currentTime;
startSponsorSchedule();
}
};
getVideo().addEventListener('play', playListener);
video.addEventListener('play', playListener);
const playingListener = () => {
updateVirtualTime();
@@ -876,8 +915,8 @@ function setupVideoListeners() {
if (startedWaiting) {
startedWaiting = false;
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)}`);
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)}`);
}
if (switchingVideos) {
@@ -889,63 +928,63 @@ function setupVideoListeners() {
}
// Make sure it doesn't get double called with the play event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) {
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime;
lastCheckVideoTime = video.currentTime;
startSponsorSchedule();
}
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastPlaybackSpeed = getVideo().playbackRate;
lastPlaybackSpeed = video.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) {
if ((!getVideoID() || video.paused) && playbackRateCheckInterval) {
// Video is gone, stop checking
clearInterval(playbackRateCheckInterval);
return;
}
if (getVideo().playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = getVideo().playbackRate;
if (video.playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = video.playbackRate;
rateChangeListener();
}
}, 2000);
}
};
getVideo().addEventListener('playing', playingListener);
video.addEventListener('playing', playingListener);
const seekingListener = () => {
lastKnownVideoTime.fromPause = false;
if (!getVideo().paused){
if (!video.paused){
// Reset lastCheckVideoTime
lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime;
lastCheckVideoTime = video.currentTime;
updateVirtualTime();
clearWaitingTime();
// Sometimes looped videos loop back to almost zero, but not quite
if (getVideo().loop && getVideo().currentTime < 0.2) {
if (video.loop && video.currentTime < 0.2) {
startSponsorSchedule(false, 0);
} else {
startSponsorSchedule();
}
} else {
updateActiveSegment(getVideo().currentTime);
updateActiveSegment(video.currentTime);
if (getVideo().currentTime === 0) {
if (video.currentTime === 0) {
lastPausedAtZero = true;
}
}
};
getVideo().addEventListener('seeking', seekingListener);
video.addEventListener('seeking', seekingListener);
const stoppedPlayback = () => {
// Reset lastCheckVideoTime
@@ -956,7 +995,7 @@ function setupVideoListeners() {
lastKnownVideoTime.videoTime = null;
lastKnownVideoTime.preciseTime = null;
updateWaitingTime();
updateWaitingTime(video);
cancelSponsorSchedule();
};
@@ -965,26 +1004,26 @@ function setupVideoListeners() {
stoppedPlayback();
};
getVideo().addEventListener('pause', pauseListener);
video.addEventListener('pause', pauseListener);
const waitingListener = () => {
logDebug("[SB] Not skipping due to buffering");
startedWaiting = true;
stoppedPlayback();
};
getVideo().addEventListener('waiting', waitingListener);
video.addEventListener('waiting', waitingListener);
startSponsorSchedule();
if (setupVideoListenersFirstTime) {
addCleanupListener(() => {
getVideo().removeEventListener('play', playListener);
getVideo().removeEventListener('playing', playingListener);
getVideo().removeEventListener('seeking', seekingListener);
getVideo().removeEventListener('ratechange', rateChangeListener);
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener);
getVideo().removeEventListener('pause', pauseListener);
getVideo().removeEventListener('waiting', waitingListener);
video.removeEventListener('play', playListener);
video.removeEventListener('playing', playingListener);
video.removeEventListener('seeking', seekingListener);
video.removeEventListener('ratechange', rateChangeListener);
video.removeEventListener('videoSpeed_ratechange', rateChangeListener);
video.removeEventListener('pause', pauseListener);
video.removeEventListener('waiting', waitingListener);
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
});
@@ -1035,8 +1074,8 @@ function updateVirtualTime() {
}
}
function updateWaitingTime(): void {
lastTimeFromWaitingEvent = getVideo().currentTime;
function updateWaitingTime(video: HTMLVideoElement): void {
lastTimeFromWaitingEvent = video.currentTime;
}
function clearWaitingTime(): void {
@@ -1070,17 +1109,6 @@ function setupCategoryPill() {
}
async function sponsorsLookup(keepOldSubmissions = true) {
if (lookupWaiting) return;
//there is still no video here
if (!getVideo()) {
lookupWaiting = true;
setTimeout(() => {
lookupWaiting = false;
sponsorsLookup()
}, 100);
return;
}
const categories: string[] = Config.config.categorySelections.map((category) => category.name);
const extraRequestData: Record<string, unknown> = {};
@@ -1157,13 +1185,14 @@ async function sponsorsLookup(keepOldSubmissions = true) {
}
}
if (!getVideo()) {
//there is still no video here
await waitFor(() => getVideo(), 5000, 10);
}
startSkipScheduleCheckingForStartSponsors();
//update the preview bar
//leave the type blank for now until categories are added
if (lastPreviewBarUpdate == getVideoID() || (lastPreviewBarUpdate == null && !isNaN(getVideo().duration))) {
//set it now
//otherwise the listener can handle it
if (!isNaN(getVideo().duration)) {
updatePreviewBar();
}
} else {
@@ -1181,7 +1210,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
found: sponsorDataFound,
status: lastResponseStatus,
sponsorTimes: sponsorTimes,
time: getVideo().currentTime,
time: getVideo()?.currentTime ?? 0,
onMobileYouTube: isOnMobileYouTube()
});
@@ -1191,10 +1220,10 @@ async function sponsorsLookup(keepOldSubmissions = true) {
}
function importExistingChapters(wait: boolean) {
if (!existingChaptersImported) {
if (!existingChaptersImported && !importingChaptersWaiting && !triedImportingChapters && onVideoPage() && !isOnMobileYouTube()) {
const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration);
if (!waitCondition() && wait && !document.hasFocus() && !importingChaptersWaitingForFocus) {
if (wait && !document.hasFocus() && !importingChaptersWaitingForFocus && !waitCondition()) {
importingChaptersWaitingForFocus = true;
const listener = () => {
importExistingChapters(wait);
@@ -1202,14 +1231,17 @@ function importExistingChapters(wait: boolean) {
};
window.addEventListener("focus", listener);
} else {
importingChaptersWaiting = true;
waitFor(waitCondition,
wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => {
importingChaptersWaiting = false;
if (!existingChaptersImported && chapters?.length > 0) {
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
existingChaptersImported = true;
updatePreviewBar();
}
}).catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
}).catch(() => { importingChaptersWaiting = false; triedImportingChapters = true; }); // eslint-disable-line @typescript-eslint/no-empty-function
}
}
}
@@ -1381,9 +1413,6 @@ function updatePreviewBar(): void {
showTimeWithoutSkips(skippedDuration);
}
// Update last video id
lastPreviewBarUpdate = getVideoID();
}
//checks if this channel is whitelisted, should be done only after the channelID has been loaded
@@ -1407,7 +1436,8 @@ function videoElementChange(newVideo: boolean): void {
setupSkipButtonControlBar();
setupCategoryPill();
}
updatePreviewBar();
checkPreviewbarState();
// Incase the page is still transitioning, check again in a few seconds
@@ -1417,8 +1447,19 @@ function videoElementChange(newVideo: boolean): void {
})
}
let checkingPreviewbarAgain = false;
function checkPreviewbarState(): void {
if (previewBar && !utils.findReferenceNode()?.contains(previewBar.container)) {
if (!getPreviewBarAttachElement() && !checkingPreviewbarAgain && getVideo() && getVideoID()) {
checkingPreviewbarAgain = true;
setTimeout(() => {
checkingPreviewbarAgain = false;
checkPreviewbarState();
}, 500);
return;
}
if (previewBar && !getPreviewBarAttachElement()?.contains(previewBar.container)) {
previewBar.remove();
previewBar = null;
}
@@ -1600,6 +1641,13 @@ function previewTime(time: number, unpause = true) {
//send telemetry and count skip
function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: number, fullSkip: boolean) {
for (const segment of skippingSegments) {
if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
// Count that as a previewed segment
previewedSegment = true;
}
}
if (!Config.config.trackViewCount || (!Config.config.trackViewCountInPrivate && chrome.extension.inIncognitoContext)) return;
let counted = false;
@@ -1616,9 +1664,6 @@ 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;
}
}
}
@@ -1629,8 +1674,9 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
// There will only be one submission if it is manual skip
const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]);
const isSubmittingSegment = sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment);
if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment))
if ((autoSkip || isSubmittingSegment)
&& v.currentTime !== skipTime[1]) {
switch(skippingSegments[0].actionType) {
case ActionType.Poi:
@@ -1711,7 +1757,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
}
//send telemetry that a this sponsor was skipped
if (autoSkip) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true);
if (autoSkip || isSubmittingSegment) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true);
}
function createSkipNotice(skippingSegments: SponsorTime[], autoSkip: boolean, unskipTime: number, startReskip: boolean) {
@@ -1801,7 +1847,8 @@ function shouldAutoSkip(segment: SponsorTime): boolean {
return (!Config.config.manualSkipOnFullVideo || !sponsorTimes?.some((s) => s.category === segment.category && s.actionType === ActionType.Full))
&& (utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
&& segment.actionType === ActionType.Skip));
&& segment.actionType === ActionType.Skip)
|| sponsorTimesSubmitting.some((s) => s.segment === segment.segment));
}
function shouldSkip(segment: SponsorTime): boolean {
@@ -2668,3 +2715,22 @@ function setCategoryColorCSSVariables() {
styleContainer.innerText = css;
}
/**
* If mini player starts playing, then videoID change might have to be called
*/
function checkForMiniplayerPlaying() {
const miniPlayerUI = document.querySelector(".miniplayer") as HTMLElement;
if (!onVideoPage() && isVisible(miniPlayerUI)) {
const videoID = getLastNonInlineVideoID();
if (videoID) {
triggerVideoIDChange(videoID);
// treat as if video element has changed
const video = miniPlayerUI.querySelector("video") as HTMLVideoElement;
if (video && getVideo() !== video) {
triggerVideoElementChange(video);
}
}
}
}

View File

@@ -13,6 +13,7 @@ import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
import { normalizeChapterName } from "../utils/exporter";
import { findValidElement } from "../../maze-utils/src/dom";
import { addCleanupListener } from "../../maze-utils/src/cleanup";
import { isVisible } from "../utils/pageUtils";
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
const MIN_CHAPTER_SIZE = 0.003;
@@ -225,10 +226,12 @@ class PreviewBar {
this.segments = segments ?? [];
this.videoDuration = videoDuration ?? 0;
this.updatePageElements();
// Sometimes video duration is inaccurate, pull from accessibility info
const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0;
if (ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
const multipleActiveVideos = [...document.querySelectorAll("video")].filter((v) => isVisible(v)).length > 1;
if (!multipleActiveVideos && ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
this.videoDuration = ariaDuration;
}
@@ -236,7 +239,7 @@ class PreviewBar {
}
private updatePageElements(): void {
const allProgressBars = document.querySelectorAll('.ytp-progress-bar') as NodeListOf<HTMLElement>;
const allProgressBars = document.querySelectorAll(".ytp-progress-bar") as NodeListOf<HTMLElement>;
this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0];
if (this.progressBar) {

View File

@@ -561,7 +561,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
return true;
}
})
.sort((a, b) => a.segment[1] - b.segment[1])
.sort((a, b) => b.segment[1] - a.segment[1])
.sort((a, b) => a.segment[0] - b.segment[0]);
//add them as buttons to the issue reporting container

View File

@@ -53,24 +53,23 @@ export function importTimes(data: string, videoDuration: number): SponsorTime[]
titleRight = removeIf(split2[split2.length - 1], specialCharMatchers)
const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight;
if (title) {
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
const segment: SponsorTime = {
segment: [startTime, getFormattedTimeToSeconds(match[1])],
category: determinedCategory ?? ("chapter" as Category),
actionType: determinedCategory ? ActionType.Skip : ActionType.Chapter,
description: title,
source: SponsorSourceType.Local,
UUID: generateUserID() as SegmentUUID
};
const category = title ? (determinedCategory ?? ("chapter" as Category)) : "chooseACategory" as Category;
const segment: SponsorTime = {
segment: [startTime, getFormattedTimeToSeconds(match[1])],
category,
actionType: category === "chapter" ? ActionType.Chapter : ActionType.Skip,
description: category === "chapter" ? title : null,
source: SponsorSourceType.Local,
UUID: generateUserID() as SegmentUUID
};
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
result[result.length - 1].segment[1] = segment.segment[0];
}
result.push(segment);
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
result[result.length - 1].segment[1] = segment.segment[0];
}
result.push(segment);
}
}
}