diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index 2c8781b4..43619844 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -32,6 +32,7 @@ sponsorBlockCategoriesStore, sponsorBlockDisplayToastStore, sponsorBlockStore, + sponsorBlockTimelineStore, sponsorBlockUrlStore, synciousInstanceStore, synciousStore @@ -43,19 +44,62 @@ export let player: MediaPlayerElement; export let isSyncing: boolean = false; export let isEmbed: boolean = false; + export let segments: Segment[] = []; let src: PlayerSrc = []; let categoryBeingSkipped = ''; let playerIsLive = false; let playerPosSet = false; - let segments: Segment[]; - let userVideoSpeed = 1; let silenceIsFastForwarding = false; let silenceSkipperInterval: NodeJS.Timeout; + let sponsorBlockElements: Element[] = []; + + function setSponsorTimeline() { + if (!get(sponsorBlockTimelineStore)) return; + if (segments.length === 0) return; + + const timeline = document.getElementsByClassName('vds-time-slider')[0]; + + if (sponsorBlockElements.length > 0) { + sponsorBlockElements.forEach((barDiv) => { + if (timeline.contains(barDiv)) { + timeline.removeChild(barDiv); + } + }); + } + + const segmentColors = { + sponsor: '00d400', + selfpromo: 'ffff00', + interaction: 'cc00ff', + intro: '00ffff', + outro: '0202ed', + preview: '008fd6', + music_offtopic: 'ff9900', + filler: '7300FF' + }; + + segments.forEach((segment) => { + const startPercent = (segment.startTime / data.video.lengthSeconds) * 100; + const endPercent = (segment.endTime / data.video.lengthSeconds) * 100; + const widthPercent = endPercent - startPercent; + + const barDiv = document.createElement('div'); + barDiv.classList.add('sponsorskip-bar'); + barDiv.style.left = `${startPercent}%`; + barDiv.style.width = `${widthPercent}%`; + barDiv.style.backgroundColor = + segment.category in segmentColors ? `#${segmentColors[segment.category]}` : 'grey'; + + timeline.appendChild(barDiv); + sponsorBlockElements.push(barDiv); + }); + } + function loadTimeFromUrl(page: Page): boolean { if (player) { const timeGivenUrl = page.url.searchParams.get('time'); @@ -250,6 +294,12 @@ get(sponsorBlockCategoriesStore) as Category[] ); + setSponsorTimeline(); + + addEventListener('resize', () => { + setSponsorTimeline(); + }); + player.addEventListener('time-update', (event: MediaTimeUpdateEvent) => { segments.forEach((segment) => { if ( diff --git a/materialious/src/lib/Settings.svelte b/materialious/src/lib/Settings.svelte index 351adee6..8ec9d1fb 100644 --- a/materialious/src/lib/Settings.svelte +++ b/materialious/src/lib/Settings.svelte @@ -36,6 +36,7 @@ sponsorBlockCategoriesStore, sponsorBlockDisplayToastStore, sponsorBlockStore, + sponsorBlockTimelineStore, sponsorBlockUrlStore, synciousInstanceStore, synciousStore, @@ -552,6 +553,20 @@ + +

{$_('layout.sponsors.Catagories')}

diff --git a/materialious/src/lib/i18n/locales/en.json b/materialious/src/lib/i18n/locales/en.json index b1228608..d7bff6a3 100644 --- a/materialious/src/lib/i18n/locales/en.json +++ b/materialious/src/lib/i18n/locales/en.json @@ -130,6 +130,7 @@ "sponsors": { "sponsor": "Sponsor", "disableToast": "Disable toast", + "disableTimeline": "Disable segments on timeline", "Catagories": "Catagories", "unpaidSelfPromotion": "Unpaid/Self Promotion", "interactionReminder": "Interaction Reminder (Subscribe)", diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index 1968e8ee..fdd2f72c 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -72,6 +72,10 @@ export const sponsorBlockDisplayToastStore: Writable = persisted( 'sponsorBlockDisplayToast', false ); +export const sponsorBlockTimelineStore: Writable = persisted( + 'sponsorBlockTimeline', + true +); export const deArrowInstanceStore = persisted( 'deArrowInstance', @@ -93,5 +97,4 @@ export const playlistSettingsStore: Writable = writable(null); - export const silenceSkipperStore: Writable = persisted('silenceSkipper', false); diff --git a/materialious/src/routes/(app)/watch/[slug]/+page.svelte b/materialious/src/routes/(app)/watch/[slug]/+page.svelte index 708de8af..4fc47913 100644 --- a/materialious/src/routes/(app)/watch/[slug]/+page.svelte +++ b/materialious/src/routes/(app)/watch/[slug]/+page.svelte @@ -40,6 +40,7 @@ } from '$lib/store'; import { mergeMediaFromDASH } from '$lib/videoDownload'; import type { DataConnection } from 'peerjs'; + import { type Segment } from 'sponsorblock-api'; import { onDestroy, onMount } from 'svelte'; import { _ } from 'svelte-i18n'; import { get } from 'svelte/store'; @@ -74,6 +75,8 @@ let audioMode = get(playerListenByDefaultStore); let player: MediaPlayerElement; + let segments: Segment[] = []; + let showTranscript = false; playlistSettingsStore.subscribe((playlistSetting) => { @@ -454,7 +457,13 @@
- +
{/key} diff --git a/materialious/static/style.css b/materialious/static/style.css index 52396fbe..6fedc174 100644 --- a/materialious/static/style.css +++ b/materialious/static/style.css @@ -27,6 +27,19 @@ margin-right: 5px !important; } +.sponsorskip-bar { + position: absolute; + margin-top: 2px; + height: 5px; + top: -1; + border-radius: 1em; +} + +.vds-time-slider { + position: relative !important; + width: 100% !important; +} + .vds-poster :where(img) { object-fit: cover !important; }