mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-08 12:37:05 +03:00
Improve next chapter and previous chapter keybind
This commit is contained in:
@@ -71,6 +71,10 @@ let lastKnownVideoTime: { videoTime: number, preciseTime: number } = {
|
|||||||
};
|
};
|
||||||
// It resumes with a slightly later time on chromium
|
// It resumes with a slightly later time on chromium
|
||||||
let lastTimeFromWaitingEvent = null;
|
let lastTimeFromWaitingEvent = null;
|
||||||
|
const lastNextChapterKeybind = {
|
||||||
|
time: 0,
|
||||||
|
date: 0
|
||||||
|
};
|
||||||
|
|
||||||
// Skips are scheduled to ensure precision.
|
// Skips are scheduled to ensure precision.
|
||||||
// Skips are rescheduled every seeking event.
|
// Skips are rescheduled every seeking event.
|
||||||
@@ -2233,30 +2237,39 @@ function updateActiveSegment(currentTime: number): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nextChapter(): void {
|
function nextChapter(): void {
|
||||||
const chapters = sponsorTimes.filter((time) => time.actionType === ActionType.Chapter)
|
const chapters = previewBar.chapterGroups?.filter((time) => [ActionType.Chapter, null].includes(time.actionType));
|
||||||
.sort((a, b) => a.segment[1] - b.segment[1]);
|
if (!chapters || chapters.length <= 0) return;
|
||||||
if (chapters.length <= 0) return;
|
|
||||||
|
|
||||||
const nextChapter = chapters.findIndex((time) => time.actionType === ActionType.Chapter
|
lastNextChapterKeybind.time = video.currentTime;
|
||||||
&& time.segment[1] > video.currentTime);
|
lastNextChapterKeybind.date = Date.now();
|
||||||
|
|
||||||
|
const nextChapter = chapters.findIndex((time) => time.segment[0] > video.currentTime);
|
||||||
if (nextChapter !== -1) {
|
if (nextChapter !== -1) {
|
||||||
reskipSponsorTime(chapters[nextChapter], true);
|
video.currentTime = chapters[nextChapter].segment[0];
|
||||||
} else {
|
} else {
|
||||||
video.currentTime = video.duration;
|
video.currentTime = video.duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function previousChapter(): void {
|
function previousChapter(): void {
|
||||||
const chapters = sponsorTimes.filter((time) => time.actionType === ActionType.Chapter);
|
if (Date.now() - lastNextChapterKeybind.date < 3000) {
|
||||||
if (chapters.length <= 0) return;
|
video.currentTime = lastNextChapterKeybind.time;
|
||||||
|
lastNextChapterKeybind.date = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chapters = previewBar.chapterGroups?.filter((time) => [ActionType.Chapter, null].includes(time.actionType));
|
||||||
|
if (!chapters || chapters.length <= 0) {
|
||||||
|
video.currentTime = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// subtract 5 seconds to allow skipping back to the previous chapter if close to start of
|
// subtract 5 seconds to allow skipping back to the previous chapter if close to start of
|
||||||
// the current one
|
// the current one
|
||||||
const nextChapter = chapters.findIndex((time) => time.actionType === ActionType.Chapter
|
const nextChapter = chapters.findIndex((time) => time.segment[0] > video.currentTime - Math.min(5, time.segment[1] - time.segment[0]));
|
||||||
&& time.segment[0] > video.currentTime - Math.min(5, time.segment[1] - time.segment[0]));
|
|
||||||
const previousChapter = nextChapter !== -1 ? (nextChapter - 1) : (chapters.length - 1);
|
const previousChapter = nextChapter !== -1 ? (nextChapter - 1) : (chapters.length - 1);
|
||||||
if (previousChapter !== -1) {
|
if (previousChapter !== -1) {
|
||||||
unskipSponsorTime(chapters[previousChapter], null, true);
|
video.currentTime = chapters[previousChapter].segment[0];
|
||||||
} else {
|
} else {
|
||||||
video.currentTime = 0;
|
video.currentTime = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ export interface PreviewBarSegment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ChapterGroup extends SegmentContainer {
|
interface ChapterGroup extends SegmentContainer {
|
||||||
originalDuration: number
|
originalDuration: number;
|
||||||
|
actionType: ActionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreviewBar {
|
class PreviewBar {
|
||||||
@@ -54,6 +55,7 @@ class PreviewBar {
|
|||||||
originalChapterBar: HTMLElement;
|
originalChapterBar: HTMLElement;
|
||||||
originalChapterBarBlocks: NodeListOf<HTMLElement>;
|
originalChapterBarBlocks: NodeListOf<HTMLElement>;
|
||||||
chapterMargin: number;
|
chapterMargin: number;
|
||||||
|
chapterGroups: ChapterGroup[];
|
||||||
|
|
||||||
constructor(parent: HTMLElement, onMobileYouTube: boolean, onInvidious: boolean, chapterVote: ChapterVote, test=false) {
|
constructor(parent: HTMLElement, onMobileYouTube: boolean, onInvidious: boolean, chapterVote: ChapterVote, test=false) {
|
||||||
if (test) return;
|
if (test) return;
|
||||||
@@ -308,26 +310,21 @@ class PreviewBar {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segments.every((segments) => segments.source === SponsorSourceType.YouTube)
|
|
||||||
|| (!Config.config.renderSegmentsAsChapters
|
|
||||||
&& segments.every((segment) => segment.actionType !== ActionType.Chapter
|
|
||||||
|| segment.source === SponsorSourceType.YouTube))) {
|
|
||||||
if (this.customChaptersBar) this.customChaptersBar.style.display = "none";
|
|
||||||
this.originalChapterBar.style.removeProperty("display");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge overlapping chapters
|
// Merge overlapping chapters
|
||||||
const filteredSegments = segments?.filter((segment) => this.chapterFilter(segment));
|
const filteredSegments = segments?.filter((segment) => this.chapterFilter(segment));
|
||||||
const chaptersToRender = this.createChapterRenderGroups(filteredSegments).filter((segment) => this.chapterGroupFilter(segment));
|
this.chapterGroups = this.createChapterRenderGroups(filteredSegments).filter((segment) => this.chapterGroupFilter(segment));
|
||||||
// Fix missing sections due to filtered segments
|
// Fix missing sections due to filtered segments
|
||||||
for (let i = 1; i < chaptersToRender.length; i++) {
|
for (let i = 1; i < this.chapterGroups.length; i++) {
|
||||||
if (chaptersToRender[i].segment[0] !== chaptersToRender[i - 1].segment[1]) {
|
if (this.chapterGroups[i].segment[0] !== this.chapterGroups[i - 1].segment[1]) {
|
||||||
chaptersToRender[i - 1].segment[1] = chaptersToRender[i].segment[0]
|
this.chapterGroups[i - 1].segment[1] = this.chapterGroups[i].segment[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chaptersToRender?.length <= 0) {
|
if (segments.every((segments) => segments.source === SponsorSourceType.YouTube)
|
||||||
|
|| (!Config.config.renderSegmentsAsChapters
|
||||||
|
&& segments.every((segment) => segment.actionType !== ActionType.Chapter
|
||||||
|
|| segment.source === SponsorSourceType.YouTube))
|
||||||
|
|| this.chapterGroups?.length <= 0) {
|
||||||
if (this.customChaptersBar) this.customChaptersBar.style.display = "none";
|
if (this.customChaptersBar) this.customChaptersBar.style.display = "none";
|
||||||
this.originalChapterBar.style.removeProperty("display");
|
this.originalChapterBar.style.removeProperty("display");
|
||||||
return;
|
return;
|
||||||
@@ -349,15 +346,15 @@ class PreviewBar {
|
|||||||
const originalSection = originalSections[0];
|
const originalSection = originalSections[0];
|
||||||
|
|
||||||
// For switching to a video with less chapters
|
// For switching to a video with less chapters
|
||||||
if (originalSections.length > chaptersToRender.length) {
|
if (originalSections.length > this.chapterGroups.length) {
|
||||||
for (let i = originalSections.length - 1; i >= chaptersToRender.length; i--) {
|
for (let i = originalSections.length - 1; i >= this.chapterGroups.length; i--) {
|
||||||
this.customChaptersBar.removeChild(originalSections[i]);
|
this.customChaptersBar.removeChild(originalSections[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify it to have sections for each segment
|
// Modify it to have sections for each segment
|
||||||
for (let i = 0; i < chaptersToRender.length; i++) {
|
for (let i = 0; i < this.chapterGroups.length; i++) {
|
||||||
const chapter = chaptersToRender[i].segment;
|
const chapter = this.chapterGroups[i].segment;
|
||||||
let newSection = originalSections[i] as HTMLElement;
|
let newSection = originalSections[i] as HTMLElement;
|
||||||
if (!newSection) {
|
if (!newSection) {
|
||||||
newSection = originalSection.cloneNode(true) as HTMLElement;
|
newSection = originalSection.cloneNode(true) as HTMLElement;
|
||||||
@@ -368,7 +365,7 @@ class PreviewBar {
|
|||||||
this.firstTimeSetupChapterSection(newSection);
|
this.firstTimeSetupChapterSection(newSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setupChapterSection(newSection, chapter[0], chapter[1], i !== chaptersToRender.length - 1);
|
this.setupChapterSection(newSection, chapter[0], chapter[1], i !== this.chapterGroups.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide old bar
|
// Hide old bar
|
||||||
@@ -414,11 +411,13 @@ class PreviewBar {
|
|||||||
result.push({
|
result.push({
|
||||||
segment: [segment.segment[0], segment.segment[1]],
|
segment: [segment.segment[0], segment.segment[1]],
|
||||||
originalDuration: segmentDuration,
|
originalDuration: segmentDuration,
|
||||||
|
actionType: segment.actionType
|
||||||
});
|
});
|
||||||
if (latestValidChapter?.segment[1] > segment.segment[1]) {
|
if (latestValidChapter?.segment[1] > segment.segment[1]) {
|
||||||
result.push({
|
result.push({
|
||||||
segment: [segment.segment[1], latestValidChapter.segment[1]],
|
segment: [segment.segment[1], latestValidChapter.segment[1]],
|
||||||
originalDuration: latestValidChapter.originalDuration
|
originalDuration: latestValidChapter.originalDuration,
|
||||||
|
actionType: latestValidChapter.actionType
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +436,8 @@ class PreviewBar {
|
|||||||
// Start at end of old one otherwise
|
// Start at end of old one otherwise
|
||||||
result.push({
|
result.push({
|
||||||
segment: [latestChapter.segment[1], segment.segment[1]],
|
segment: [latestChapter.segment[1], segment.segment[1]],
|
||||||
originalDuration: segmentDuration
|
originalDuration: segmentDuration,
|
||||||
|
actionType: segment.actionType
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -446,7 +446,8 @@ class PreviewBar {
|
|||||||
if (segment.segment[0] > lastTime) {
|
if (segment.segment[0] > lastTime) {
|
||||||
result.push({
|
result.push({
|
||||||
segment: [lastTime, segment.segment[0]],
|
segment: [lastTime, segment.segment[0]],
|
||||||
originalDuration: 0
|
originalDuration: 0,
|
||||||
|
actionType: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +455,8 @@ class PreviewBar {
|
|||||||
const endTime = Math.min(segment.segment[1], this.videoDuration);
|
const endTime = Math.min(segment.segment[1], this.videoDuration);
|
||||||
result.push({
|
result.push({
|
||||||
segment: [segment.segment[0], endTime],
|
segment: [segment.segment[0], endTime],
|
||||||
originalDuration: endTime - segment.segment[0]
|
originalDuration: endTime - segment.segment[0],
|
||||||
|
actionType: segment.actionType
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +468,8 @@ class PreviewBar {
|
|||||||
if (this.intervalToDecimal(lastTime, nextTime) > MIN_CHAPTER_SIZE) {
|
if (this.intervalToDecimal(lastTime, nextTime) > MIN_CHAPTER_SIZE) {
|
||||||
result.push({
|
result.push({
|
||||||
segment: [lastTime, nextTime],
|
segment: [lastTime, nextTime],
|
||||||
originalDuration: 0
|
originalDuration: 0,
|
||||||
|
actionType: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user