diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index fa66894f..5ec3f3e3 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -182,15 +182,15 @@ "hideButtonsDescription": { "message": "This hides the buttons that appear on the YouTube player to submit skip segments." }, + "showSkipButton": { + "message": "Keep Skip to Highlight Button on Player" + }, "showInfoButton": { "message": "Show Info Button On YouTube Player" }, "hideInfoButton": { "message": "Hide Info Button On YouTube Player" }, - "whatInfoButton": { - "message": "This is the button that opens up a popup in the YouTube page." - }, "autoHideInfoButton": { "message": "Auto-hide Info Button" }, @@ -200,9 +200,6 @@ "showDeleteButton": { "message": "Show Delete Button On YouTube Player" }, - "whatDeleteButton": { - "message": "This is the button on the YouTube player that will clear all your un-submitted segments for the current video." - }, "enableViewTracking": { "message": "Enable Skip Count Tracking" }, @@ -442,9 +439,6 @@ "showUploadButton": { "message": "Show Upload Button" }, - "whatUploadButton": { - "message": "This button appears on the YouTube player after you have selected a timestamp and are ready to submit." - }, "customServerAddress": { "message": "SponsorBlock Server Address" }, diff --git a/public/content.css b/public/content.css index 13cab8e4..5fabc94d 100644 --- a/public/content.css +++ b/public/content.css @@ -75,16 +75,26 @@ vertical-align: top; } -#infoButton.playerButton:not(.hidden) { - transform: translateX(0%) scale(1); - /* opacity is from YouTube page */ - transition: transform 0.2s, opacity .1s cubic-bezier(0.4,0.0,1,1) !important; +.autoHiding { + overflow: visible !important; } -#infoButton.playerButton.hidden { +.autoHiding:not(.hidden) { + transform: translateX(0%) scale(1); + /* opacity is from YouTube page */ + transition: transform 0.25s, width 0.25s, opacity .1s cubic-bezier(0.4,0.0,1,1) !important; +} + +.autoHiding.hidden { transform: translateX(100%) scale(0); /* opacity is from YouTube page */ - transition: transform 0.2s, opacity .1s cubic-bezier(0.4,0.0,1,1) !important; + transition: transform 0.25s, width 0.25s, opacity .1s cubic-bezier(0.4,0.0,1,1) !important; + + width: 0px !important; +} + +.autoHiding.hidden.autoHideLeft { + transform: translateX(-100%) scale(0); } .playerButton.hidden { diff --git a/public/options/options.html b/public/options/options.html index b1a0dcb4..1fbcf1b1 100644 --- a/public/options/options.html +++ b/public/options/options.html @@ -287,7 +287,22 @@
__MSG_hideButtonsDescription__
+ +
+ +
+ +
+


@@ -301,14 +316,9 @@ __MSG_showInfoButton__ - -
-
-
- -
__MSG_whatInfoButton__
+


@@ -322,13 +332,11 @@ __MSG_autoHideInfoButton__ - -
-
-
- -
+ +
+
+
- -
-
-
- -
__MSG_whatDeleteButton__
+


@@ -361,14 +364,10 @@ __MSG_showUploadButton__ - -
-
-
- -
__MSG_whatUploadButton__
+
+


diff --git a/src/config.ts b/src/config.ts index 8bcdc061..5d8a58e4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -26,6 +26,7 @@ interface SBConfig { hideInfoButtonPlayerControls: boolean, hideDeleteButtonPlayerControls: boolean, hideUploadButtonPlayerControls: boolean, + hideSkipButtonPlayerControls: boolean, hideDiscordLaunches: number, hideDiscordLink: boolean, invidiousInstances: string[], @@ -172,6 +173,7 @@ const Config: SBObject = { hideInfoButtonPlayerControls: false, hideDeleteButtonPlayerControls: false, hideUploadButtonPlayerControls: false, + hideSkipButtonPlayerControls: false, hideDiscordLaunches: 0, hideDiscordLink: false, invidiousInstances: ["invidious.snopyta.org"], diff --git a/src/content.ts b/src/content.ts index 56647c99..6d1dab93 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1307,15 +1307,8 @@ async function createButtons(): Promise { if (Config.config.autoHideInfoButton && !onInvidious && controlsContainer && playerButtons["info"]?.button && !controlsWithEventListeners.includes(controlsContainer)) { controlsWithEventListeners.push(controlsContainer); - playerButtons["info"].button.classList.add("hidden"); - - controlsContainer.addEventListener("mouseenter", () => { - playerButtons["info"].button.classList.remove("hidden"); - }); - - controlsContainer.addEventListener("mouseleave", () => { - playerButtons["info"].button.classList.add("hidden"); - }); + + utils.setupAutoHideAnimation(playerButtons["info"].button, controlsContainer); } } diff --git a/src/js-components/skipButtonControlBar.ts b/src/js-components/skipButtonControlBar.ts index 1ea03724..a3e47362 100644 --- a/src/js-components/skipButtonControlBar.ts +++ b/src/js-components/skipButtonControlBar.ts @@ -2,6 +2,8 @@ import Config from "../config"; import { SponsorTime } from "../types"; import { getSkippingText } from "../utils/categoryUtils"; +import Utils from "../utils"; +const utils = new Utils(); export interface SkipButtonControlBarProps { skip: (segment: SponsorTime) => void; @@ -53,13 +55,20 @@ export class SkipButtonControlBar { if (leftControlsContainer && !leftControlsContainer.contains(this.container)) { leftControlsContainer.insertBefore(this.container, this.chapterText); + + if (Config.config.autoHideInfoButton) { + utils.setupAutoHideAnimation(this.skipIcon, leftControlsContainer, false, false); + } } } enable(segment: SponsorTime, duration?: number): void { if (duration) this.duration = duration; this.segment = segment; + this.refreshText(); + this.textContainer?.classList?.remove("hidden"); + utils.disableAutoHideAnimation(this.skipIcon); this.startTimer(); } @@ -68,7 +77,8 @@ export class SkipButtonControlBar { if (this.segment) { this.chapterText?.classList?.add("hidden"); this.container.classList.remove("hidden"); - this.textContainer.innerText = getSkippingText([this.segment], false) + (this.showKeybindHint ? " (" + Config.config.skipKeybind + ")" : ""); + this.textContainer.innerText = this.getTitle(); + this.skipIcon.setAttribute("title", this.getTitle()); } } @@ -84,17 +94,42 @@ export class SkipButtonControlBar { startTimer(): void { this.stopTimer(); - this.timeout = setTimeout(() => this.disable(), Math.max(Config.config.skipNoticeDuration, this.duration) * 1000); + this.timeout = setTimeout(() => this.disableText(), Math.max(Config.config.skipNoticeDuration, this.duration) * 1000); } disable(): void { this.container.classList.add("hidden"); + this.textContainer?.classList?.remove("hidden"); + this.chapterText?.classList?.remove("hidden"); + this.getChapterPrefix()?.classList?.remove("hidden"); } toggleSkip(): void { this.skip(this.segment); - this.disable(); + this.disableText(); + } + + disableText(): void { + if (Config.config.hideVideoPlayerControls || Config.config.hideSkipButtonPlayerControls) { + this.disable(); + return; + } + + this.textContainer?.classList?.add("hidden"); + this.chapterText?.classList?.remove("hidden"); + + this.getChapterPrefix()?.classList?.add("hidden"); + + utils.enableAutoHideAnimation(this.skipIcon); + } + + private getTitle(): string { + return getSkippingText([this.segment], false) + (this.showKeybindHint ? " (" + Config.config.skipKeybind + ")" : ""); + } + + private getChapterPrefix(): HTMLElement { + return document.querySelector(".ytp-chapter-title-prefix"); } } diff --git a/src/utils.ts b/src/utils.ts index 983c1c1b..50e332ae 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -183,6 +183,34 @@ export default class Utils { } } + setupAutoHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): void { + if (enabled) element.classList.add("autoHiding"); + element.classList.add("hidden"); + element.classList.add("animationDone"); + if (!rightSlide) element.classList.add("autoHideLeft"); + + container.addEventListener("mouseenter", () => { + element.classList.remove("animationDone"); + + // Wait for next event loop + setTimeout(() => element.classList.remove("hidden"), 10); + }); + + container.addEventListener("mouseleave", () => { + if (element.classList.contains("autoHiding")) { + element.classList.add("hidden"); + } + }); + } + + enableAutoHideAnimation(element: Element): void { + element.classList.add("autoHiding"); + } + + disableAutoHideAnimation(element: Element): void { + element.classList.remove("autoHiding"); + } + /** * Merges any overlapping timestamp ranges into single segments and returns them as a new array. */