Implemented sponsorskip on timeline and add support for automatic,
manual or timeline only
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.13.0",
|
||||
"version": "1.13.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.13.0",
|
||||
"version": "1.13.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
sponsorBlockCategoriesStore,
|
||||
sponsorBlockDisplayToastStore,
|
||||
sponsorBlockStore,
|
||||
sponsorBlockTimelineStore,
|
||||
sponsorBlockUrlStore,
|
||||
synciousInstanceStore,
|
||||
synciousStore
|
||||
@@ -71,7 +72,8 @@
|
||||
showControls = false
|
||||
}: Props = $props();
|
||||
|
||||
let segments: Segment[] = [];
|
||||
let segments: Segment[] = $state([]);
|
||||
let segmentManualSkip: Segment | undefined = $state();
|
||||
|
||||
let snackBarAlert = $state('');
|
||||
let originalOrigination: ScreenOrientationResult | undefined;
|
||||
@@ -264,20 +266,31 @@
|
||||
document.addEventListener('fullscreenchange', onAndroidFullscreenChange);
|
||||
}
|
||||
|
||||
function skipSegment(segment: Segment) {
|
||||
if (!playerElement) return;
|
||||
|
||||
segmentManualSkip = undefined;
|
||||
|
||||
if (Math.round(playerElement.currentTime) >= Math.round(playerElement.duration)) {
|
||||
return;
|
||||
}
|
||||
playerElement.currentTime = segment.endTime + 1;
|
||||
if (!get(sponsorBlockDisplayToastStore)) {
|
||||
snackBarAlert = `${get(_)('skipping')} ${segment.category}`;
|
||||
ui('#snackbar-alert');
|
||||
}
|
||||
}
|
||||
|
||||
async function setupSponsorSkip() {
|
||||
if (!$sponsorBlockUrlStore || !$sponsorBlockCategoriesStore || !$sponsorBlockStore) return;
|
||||
|
||||
if (
|
||||
$sponsorBlockCategoriesStore.length > 0 &&
|
||||
$sponsorBlockUrlStore &&
|
||||
$sponsorBlockUrlStore !== ''
|
||||
) {
|
||||
if ($sponsorBlockCategoriesStore && $sponsorBlockUrlStore && $sponsorBlockUrlStore !== '') {
|
||||
const sponsorBlock = new SponsorBlock('', { baseURL: $sponsorBlockUrlStore });
|
||||
|
||||
try {
|
||||
segments = await sponsorBlock.getSegments(
|
||||
data.video.videoId,
|
||||
$sponsorBlockCategoriesStore as Category[]
|
||||
Object.keys($sponsorBlockCategoriesStore) as Category[]
|
||||
);
|
||||
|
||||
playerElement?.addEventListener('timeupdate', () => {
|
||||
@@ -288,12 +301,13 @@
|
||||
playerElement.currentTime >= segment.startTime &&
|
||||
playerElement.currentTime <= segment.endTime
|
||||
) {
|
||||
if (Math.round(playerElement.currentTime) >= Math.round(playerElement.duration)) {
|
||||
return;
|
||||
}
|
||||
playerElement.currentTime = segment.endTime + 1;
|
||||
if (!get(sponsorBlockDisplayToastStore)) {
|
||||
snackBarAlert = `${get(_)('skipping')} ${segment.category}`;
|
||||
const segmentTrigger = $sponsorBlockCategoriesStore[segment.category];
|
||||
|
||||
if (segmentTrigger === 'automatic') {
|
||||
skipSegment(segment);
|
||||
} else if (segmentTrigger === 'manual') {
|
||||
snackBarAlert = `${get(_)('upcomingSegment')} ${segment.category}`;
|
||||
segmentManualSkip = segment;
|
||||
ui('#snackbar-alert');
|
||||
}
|
||||
}
|
||||
@@ -747,6 +761,12 @@
|
||||
playerElement.currentTime = playerElement.currentTime - playerDoubleTapSeek;
|
||||
return false;
|
||||
});
|
||||
|
||||
Mousetrap.bind('enter', () => {
|
||||
if (segmentManualSkip) {
|
||||
skipSegment(segmentManualSkip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Mousetrap.bind('c', () => {
|
||||
@@ -1057,7 +1077,7 @@
|
||||
|
||||
window.removeEventListener('resize', updateVideoPlayerHeight);
|
||||
|
||||
Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right']);
|
||||
Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right', 'enter']);
|
||||
|
||||
if (watchProgressInterval) clearTimeout(watchProgressInterval);
|
||||
|
||||
@@ -1170,6 +1190,15 @@
|
||||
)}
|
||||
></div>
|
||||
{/each}
|
||||
{#if !$sponsorBlockTimelineStore}
|
||||
{#each segments as segment (segment)}
|
||||
<div
|
||||
class="chapter-marker segment-marker"
|
||||
style:left="{(segment.startTime / playerMaxKnownTime) * 100}%"
|
||||
style:width={getMarkerWidth(segment.startTime, segment.endTime)}
|
||||
></div>
|
||||
{/each}
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
{#if playerTimelineTooltipVisible}
|
||||
@@ -1443,6 +1472,9 @@
|
||||
{#if !isEmbed}
|
||||
<div class="snackbar" id="snackbar-alert">
|
||||
<span class="bold" style="text-transform: capitalize;">{snackBarAlert}</span>
|
||||
{#if segmentManualSkip}
|
||||
<button onclick={() => skipSegment(segmentManualSkip as Segment)}>{$_('skip')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1547,6 +1579,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.segment-marker {
|
||||
background-color: var(--tertiary);
|
||||
}
|
||||
|
||||
menu.mobile {
|
||||
transform: scale(1) translateY(-40%) translateX(0);
|
||||
width: 300px;
|
||||
|
||||
@@ -8,14 +8,10 @@
|
||||
sponsorBlockCategoriesStore,
|
||||
sponsorBlockDisplayToastStore,
|
||||
sponsorBlockStore,
|
||||
sponsorBlockTimelineStore,
|
||||
sponsorBlockUrlStore
|
||||
} from '../../store';
|
||||
|
||||
let sponsorCategoriesList: string[] = $state([]);
|
||||
sponsorBlockCategoriesStore.subscribe((value) => {
|
||||
sponsorCategoriesList = value;
|
||||
});
|
||||
|
||||
let sponsorBlockInstance = $state(get(sponsorBlockUrlStore));
|
||||
|
||||
const sponsorCategories = [
|
||||
@@ -28,13 +24,21 @@
|
||||
{ name: $_('layout.sponsors.tangentJokes'), category: 'filler' }
|
||||
];
|
||||
|
||||
function toggleSponsor(category: string) {
|
||||
if (sponsorCategoriesList.includes(category)) {
|
||||
sponsorBlockCategoriesStore.set(sponsorCategoriesList.filter((value) => value !== category));
|
||||
function onSponsorSet(
|
||||
category: string,
|
||||
event: Event & { currentTarget: EventTarget & HTMLSelectElement }
|
||||
) {
|
||||
const value = event.currentTarget.value as 'automatic' | 'manual' | 'timeline' | 'disabled';
|
||||
|
||||
const categories = get(sponsorBlockCategoriesStore);
|
||||
|
||||
if (value !== 'disabled') {
|
||||
categories[category] = value;
|
||||
} else {
|
||||
sponsorCategoriesList.push(category);
|
||||
sponsorBlockCategoriesStore.set(sponsorCategoriesList);
|
||||
delete categories[category];
|
||||
}
|
||||
|
||||
sponsorBlockCategoriesStore.set(categories);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -89,7 +93,7 @@
|
||||
</label>
|
||||
</nav>
|
||||
|
||||
<!-- <nav class="no-padding">
|
||||
<nav class="no-padding">
|
||||
<div class="max">
|
||||
<p>{$_('layout.sponsors.disableTimeline')}</p>
|
||||
</div>
|
||||
@@ -101,27 +105,36 @@
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
</nav> -->
|
||||
</nav>
|
||||
|
||||
<hr style="margin: 1em 0;" />
|
||||
|
||||
<p class="bold">{$_('layout.sponsors.Catagories')}</p>
|
||||
|
||||
{#each sponsorCategories as sponsor (sponsor)}
|
||||
{@const currentCatergoryTrigger = $sponsorBlockCategoriesStore[sponsor.category]}
|
||||
<div class="field middle-align no-margin">
|
||||
<nav class="no-padding">
|
||||
<div class="max">
|
||||
<p>{sponsor.name}</p>
|
||||
</div>
|
||||
<label class="switch" tabindex="0">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={sponsorCategoriesList.includes(sponsor.category)}
|
||||
onclick={() => toggleSponsor(sponsor.category)}
|
||||
role="switch"
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
<div class="field suffix border">
|
||||
<select onchange={(event) => onSponsorSet(sponsor.category, event)}>
|
||||
<option selected={currentCatergoryTrigger === undefined} value="disabled"
|
||||
>{$_('disabled')}</option
|
||||
>
|
||||
<option selected={currentCatergoryTrigger === 'automatic'} value="automatic"
|
||||
>{$_('layout.sponsors.automatic')}</option
|
||||
>
|
||||
<option selected={currentCatergoryTrigger === 'manual'} value="manual"
|
||||
>{$_('layout.sponsors.manual')}</option
|
||||
>
|
||||
<option selected={currentCatergoryTrigger === 'timeline'} value="timeline"
|
||||
>{$_('layout.sponsors.timeline')}</option
|
||||
>
|
||||
</select>
|
||||
<i>arrow_drop_down</i>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
returnYTDislikesInstanceStore,
|
||||
returnYtDislikesStore,
|
||||
showWarningStore,
|
||||
sponsorBlockCategoriesStore,
|
||||
sponsorBlockDisplayToastStore,
|
||||
sponsorBlockStore,
|
||||
sponsorBlockUrlStore,
|
||||
@@ -109,11 +108,6 @@ const persistedStores: {
|
||||
store: sponsorBlockUrlStore,
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
name: 'sponsorBlockCategories',
|
||||
store: sponsorBlockCategoriesStore,
|
||||
type: 'array'
|
||||
},
|
||||
{
|
||||
name: 'deArrowInstance',
|
||||
store: deArrowInstanceStore,
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
"donate": "Donate",
|
||||
"deleteAllHistory": "Delete all history",
|
||||
"skipping": "Skipping",
|
||||
"skip": "Skip",
|
||||
"upcomingSegment": "Upcoming ",
|
||||
"comments": "comments",
|
||||
"reply": "reply",
|
||||
"replies": "replies",
|
||||
@@ -203,7 +205,10 @@
|
||||
"intermissionIntroAnimation": "Intermission/Intro Animation",
|
||||
"credits": "Endcards/Credits",
|
||||
"preViewRecapHook": "Preview/Recap/Hook",
|
||||
"tangentJokes": "Filler Tangent/Jokes"
|
||||
"tangentJokes": "Filler Tangent/Jokes",
|
||||
"automatic": "Auto skip",
|
||||
"manual": "Manual skip",
|
||||
"timeline": "Timeline only"
|
||||
},
|
||||
"deArrow": {
|
||||
"title": "DeArrow",
|
||||
|
||||
@@ -279,11 +279,10 @@ export const sponsorBlockUrlStore: Writable<string | null | undefined> = persist
|
||||
createStorage(),
|
||||
'sponsorBlockUrl'
|
||||
);
|
||||
export const sponsorBlockCategoriesStore: Writable<string[]> = persist(
|
||||
writable([]),
|
||||
createStorage(),
|
||||
'sponsorBlockCategories'
|
||||
);
|
||||
|
||||
export const sponsorBlockCategoriesStore: Writable<
|
||||
Record<string, 'automatic' | 'manual' | 'timeline' | undefined>
|
||||
> = persist(writable({}), createStorage(), 'sponsorBlockCategoriesv2');
|
||||
|
||||
export const sponsorBlockDisplayToastStore: Writable<boolean> = persist(
|
||||
writable(false),
|
||||
|
||||
Reference in New Issue
Block a user