mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-10 21:47:06 +03:00
Show both categories and chapter names in hover text
This commit is contained in:
@@ -45,23 +45,44 @@
|
|||||||
transform: translateY(-1em) !important;
|
transform: translateY(-1em) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ytp-tooltip.sponsorCategoryTooltipVisible.sponsorTwoTooltips {
|
||||||
|
transform: translateY(-2em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible {
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible {
|
||||||
transform: translateY(-2em) !important;
|
transform: translateY(-2em) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible.sponsorTwoTooltips {
|
||||||
|
transform: translateY(-4em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
#movie_player:not(.ytp-big-mode) .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper {
|
#movie_player:not(.ytp-big-mode) .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper {
|
||||||
transform: translateY(1em) !important;
|
transform: translateY(1em) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#movie_player:not(.ytp-big-mode) .ytp-tooltip.sponsorCategoryTooltipVisible.sponsorTwoTooltips > .ytp-tooltip-text-wrapper {
|
||||||
|
transform: translateY(2em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper {
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper {
|
||||||
transform: translateY(0.5em) !important;
|
transform: translateY(0.5em) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible.sponsorTwoTooltips > .ytp-tooltip-text-wrapper {
|
||||||
|
transform: translateY(1em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper > .ytp-tooltip-text {
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible > .ytp-tooltip-text-wrapper > .ytp-tooltip-text {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
transform: translateY(1em) !important;
|
transform: translateY(1em) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ytp-big-mode .ytp-tooltip.sponsorCategoryTooltipVisible.sponsorTwoTooltips > .ytp-tooltip-text-wrapper > .ytp-tooltip-text {
|
||||||
|
display: block !important;
|
||||||
|
transform: translateY(2em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
div:hover > .sponsorBlockChapterBar {
|
div:hover > .sponsorBlockChapterBar {
|
||||||
z-index: 41 !important;
|
z-index: 41 !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -970,6 +970,7 @@ function updatePreviewBar(): void {
|
|||||||
previewBarSegments.push({
|
previewBarSegments.push({
|
||||||
segment: segment.segment as [number, number],
|
segment: segment.segment as [number, number],
|
||||||
category: segment.category,
|
category: segment.category,
|
||||||
|
actionType: segment.actionType,
|
||||||
unsubmitted: false,
|
unsubmitted: false,
|
||||||
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI,
|
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI,
|
||||||
description: segment.description,
|
description: segment.description,
|
||||||
@@ -981,6 +982,7 @@ function updatePreviewBar(): void {
|
|||||||
previewBarSegments.push({
|
previewBarSegments.push({
|
||||||
segment: segment.segment as [number, number],
|
segment: segment.segment as [number, number],
|
||||||
category: segment.category,
|
category: segment.category,
|
||||||
|
actionType: segment.actionType,
|
||||||
unsubmitted: true,
|
unsubmitted: true,
|
||||||
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI,
|
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI,
|
||||||
description: segment.description,
|
description: segment.description,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ https://github.com/videosegments/videosegments/commits/f1e111bdfe231947800c6efdd
|
|||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
import { ActionType, Category, CategoryActionType, SegmentContainer, SponsorTime } from "../types";
|
import { ActionType, Category, CategoryActionType, SegmentContainer, SponsorTime } from "../types";
|
||||||
import Utils from "../utils";
|
import Utils from "../utils";
|
||||||
|
import { partition } from "../utils/arrayUtils";
|
||||||
import { getCategoryActionType } from "../utils/categoryUtils";
|
import { getCategoryActionType } from "../utils/categoryUtils";
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ const MIN_CHAPTER_SIZE = 0.003;
|
|||||||
export interface PreviewBarSegment {
|
export interface PreviewBarSegment {
|
||||||
segment: [number, number];
|
segment: [number, number];
|
||||||
category: Category;
|
category: Category;
|
||||||
|
actionType: ActionType;
|
||||||
unsubmitted: boolean;
|
unsubmitted: boolean;
|
||||||
showLarger: boolean;
|
showLarger: boolean;
|
||||||
description: string;
|
description: string;
|
||||||
@@ -29,7 +31,8 @@ interface ChapterGroup extends SegmentContainer {
|
|||||||
class PreviewBar {
|
class PreviewBar {
|
||||||
container: HTMLUListElement;
|
container: HTMLUListElement;
|
||||||
categoryTooltip?: HTMLDivElement;
|
categoryTooltip?: HTMLDivElement;
|
||||||
tooltipContainer?: HTMLElement;
|
categoryTooltipContainer?: HTMLElement;
|
||||||
|
chapterTooltip?: HTMLDivElement;
|
||||||
|
|
||||||
parent: HTMLElement;
|
parent: HTMLElement;
|
||||||
onMobileYouTube: boolean;
|
onMobileYouTube: boolean;
|
||||||
@@ -64,16 +67,19 @@ class PreviewBar {
|
|||||||
// Create label placeholder
|
// Create label placeholder
|
||||||
this.categoryTooltip = document.createElement("div");
|
this.categoryTooltip = document.createElement("div");
|
||||||
this.categoryTooltip.className = "ytp-tooltip-title sponsorCategoryTooltip";
|
this.categoryTooltip.className = "ytp-tooltip-title sponsorCategoryTooltip";
|
||||||
|
this.chapterTooltip = document.createElement("div");
|
||||||
|
this.chapterTooltip.className = "ytp-tooltip-title sponsorCategoryTooltip";
|
||||||
|
|
||||||
const tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper");
|
const tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper");
|
||||||
if (!tooltipTextWrapper || !tooltipTextWrapper.parentElement) return;
|
if (!tooltipTextWrapper || !tooltipTextWrapper.parentElement) return;
|
||||||
|
|
||||||
// Grab the tooltip from the text wrapper as the tooltip doesn't have its classes on init
|
// Grab the tooltip from the text wrapper as the tooltip doesn't have its classes on init
|
||||||
this.tooltipContainer = tooltipTextWrapper.parentElement;
|
this.categoryTooltipContainer = tooltipTextWrapper.parentElement;
|
||||||
const titleTooltip = tooltipTextWrapper.querySelector(".ytp-tooltip-title");
|
const titleTooltip = tooltipTextWrapper.querySelector(".ytp-tooltip-title");
|
||||||
if (!this.tooltipContainer || !titleTooltip) return;
|
if (!this.categoryTooltipContainer || !titleTooltip) return;
|
||||||
|
|
||||||
tooltipTextWrapper.insertBefore(this.categoryTooltip, titleTooltip.nextSibling);
|
tooltipTextWrapper.insertBefore(this.categoryTooltip, titleTooltip.nextSibling);
|
||||||
|
tooltipTextWrapper.insertBefore(this.chapterTooltip, titleTooltip.nextSibling);
|
||||||
|
|
||||||
const seekBar = document.querySelector(".ytp-progress-bar-container");
|
const seekBar = document.querySelector(".ytp-progress-bar-container");
|
||||||
if (!seekBar) return;
|
if (!seekBar) return;
|
||||||
@@ -89,7 +95,7 @@ class PreviewBar {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
const observer = new MutationObserver((mutations) => {
|
||||||
if (!mouseOnSeekBar || !this.categoryTooltip || !this.tooltipContainer) return;
|
if (!mouseOnSeekBar || !this.categoryTooltip || !this.categoryTooltipContainer) return;
|
||||||
|
|
||||||
// If the mutation observed is only for our tooltip text, ignore
|
// If the mutation observed is only for our tooltip text, ignore
|
||||||
if (mutations.length === 1 && (mutations[0].target as HTMLElement).classList.contains("sponsorCategoryTooltip")) {
|
if (mutations.length === 1 && (mutations[0].target as HTMLElement).classList.contains("sponsorCategoryTooltip")) {
|
||||||
@@ -114,37 +120,26 @@ class PreviewBar {
|
|||||||
if (timeInSeconds === null) return;
|
if (timeInSeconds === null) return;
|
||||||
|
|
||||||
// Find the segment at that location, using the shortest if multiple found
|
// Find the segment at that location, using the shortest if multiple found
|
||||||
let segment: PreviewBarSegment | null = null;
|
const [normalSegments, chapterSegments] = partition(this.segments, (segment) => segment.actionType !== ActionType.Chapter)
|
||||||
let currentSegmentLength = Infinity;
|
const normalSegment = this.getSmallestSegment(timeInSeconds, normalSegments);
|
||||||
|
const chapterSegment = this.getSmallestSegment(timeInSeconds, chapterSegments);
|
||||||
|
|
||||||
for (const seg of this.segments) {//
|
if (normalSegment === null && chapterSegment === null) {
|
||||||
const segmentLength = seg.segment[1] - seg.segment[0];
|
this.categoryTooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS);
|
||||||
const minSize = this.getMinimumSize(seg.showLarger);
|
|
||||||
|
|
||||||
const startTime = segmentLength !== 0 ? seg.segment[0] : Math.floor(seg.segment[0]);
|
|
||||||
const endTime = segmentLength > minSize ? seg.segment[1] : Math.ceil(seg.segment[0] + minSize);
|
|
||||||
if (startTime <= timeInSeconds && endTime >= timeInSeconds) {
|
|
||||||
if (segmentLength < currentSegmentLength) {
|
|
||||||
currentSegmentLength = segmentLength;
|
|
||||||
segment = seg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (segment === null && this.tooltipContainer.classList.contains(TOOLTIP_VISIBLE_CLASS)) {
|
|
||||||
this.tooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS);
|
|
||||||
} else if (segment !== null) {
|
|
||||||
this.tooltipContainer.classList.add(TOOLTIP_VISIBLE_CLASS);
|
|
||||||
|
|
||||||
const name = segment.description || utils.shortCategoryName(segment.category);
|
|
||||||
if (segment.unsubmitted) {
|
|
||||||
this.categoryTooltip.textContent = chrome.i18n.getMessage("unsubmitted") + " " + name;
|
|
||||||
} else {
|
} else {
|
||||||
this.categoryTooltip.textContent = name;
|
this.categoryTooltipContainer.classList.add(TOOLTIP_VISIBLE_CLASS);
|
||||||
|
if (noYoutubeChapters && normalSegment !== null && chapterSegment !== null) {
|
||||||
|
this.categoryTooltipContainer.classList.add("sponsorTwoTooltips");
|
||||||
|
} else {
|
||||||
|
this.categoryTooltipContainer.classList.remove("sponsorTwoTooltips");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the class if the timestamp text uses it to prevent overlapping
|
this.setTooltipTitle(normalSegment, this.categoryTooltip);
|
||||||
|
this.setTooltipTitle(chapterSegment, this.chapterTooltip);
|
||||||
|
|
||||||
|
// Used to prevent overlapping
|
||||||
this.categoryTooltip.classList.toggle("ytp-tooltip-text-no-title", noYoutubeChapters);
|
this.categoryTooltip.classList.toggle("ytp-tooltip-text-no-title", noYoutubeChapters);
|
||||||
|
this.chapterTooltip.classList.toggle("ytp-tooltip-text-no-title", noYoutubeChapters);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -154,6 +149,21 @@ class PreviewBar {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setTooltipTitle(segment: PreviewBarSegment, tooltip: HTMLElement): void {
|
||||||
|
if (segment) {
|
||||||
|
const name = segment.description || utils.shortCategoryName(segment.category);
|
||||||
|
if (segment.unsubmitted) {
|
||||||
|
tooltip.textContent = chrome.i18n.getMessage("unsubmitted") + " " + name;
|
||||||
|
} else {
|
||||||
|
tooltip.textContent = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip.style.removeProperty("display");
|
||||||
|
} else {
|
||||||
|
tooltip.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
createElement(parent: HTMLElement): void {
|
createElement(parent: HTMLElement): void {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
@@ -495,9 +505,9 @@ class PreviewBar {
|
|||||||
this.categoryTooltip = undefined;
|
this.categoryTooltip = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.tooltipContainer) {
|
if (this.categoryTooltipContainer) {
|
||||||
this.tooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS);
|
this.categoryTooltipContainer.classList.remove(TOOLTIP_VISIBLE_CLASS);
|
||||||
this.tooltipContainer = undefined;
|
this.categoryTooltipContainer = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,6 +534,27 @@ class PreviewBar {
|
|||||||
getMinimumSize(showLarger = false): number {
|
getMinimumSize(showLarger = false): number {
|
||||||
return this.videoDuration * (showLarger ? 0.006 : 0.003);
|
return this.videoDuration * (showLarger ? 0.006 : 0.003);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSmallestSegment(timeInSeconds: number, segments: PreviewBarSegment[]): PreviewBarSegment | null {
|
||||||
|
let segment: PreviewBarSegment | null = null;
|
||||||
|
let currentSegmentLength = Infinity;
|
||||||
|
|
||||||
|
for (const seg of segments) { //
|
||||||
|
const segmentLength = seg.segment[1] - seg.segment[0];
|
||||||
|
const minSize = this.getMinimumSize(seg.showLarger);
|
||||||
|
|
||||||
|
const startTime = segmentLength !== 0 ? seg.segment[0] : Math.floor(seg.segment[0]);
|
||||||
|
const endTime = segmentLength > minSize ? seg.segment[1] : Math.ceil(seg.segment[0] + minSize);
|
||||||
|
if (startTime <= timeInSeconds && endTime >= timeInSeconds) {
|
||||||
|
if (segmentLength < currentSegmentLength) {
|
||||||
|
currentSegmentLength = segmentLength;
|
||||||
|
segment = seg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PreviewBar;
|
export default PreviewBar;
|
||||||
|
|||||||
6
src/utils/arrayUtils.ts
Normal file
6
src/utils/arrayUtils.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export function partition<T>(array: T[], filter: (element: T) => boolean): [T[], T[]] {
|
||||||
|
const pass = [], fail = [];
|
||||||
|
array.forEach((element) => (filter(element) ? pass : fail).push(element));
|
||||||
|
|
||||||
|
return [pass, fail];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user