mirror of
https://github.com/TeamPiped/Piped.git
synced 2024-08-14 23:57:27 +00:00
Merge pull request #2055 from 9ary/sponsorblock-for-upstream
Add more options for sponsorblock
This commit is contained in:
commit
f9d405781a
5 changed files with 152 additions and 161 deletions
|
@ -184,83 +184,13 @@
|
|||
/>
|
||||
</label>
|
||||
<div v-if="sponsorBlock">
|
||||
<label class="pref" for="chkSkipSponsors">
|
||||
<strong v-t="'actions.skip_sponsors'" />
|
||||
<input
|
||||
id="chkSkipSponsors"
|
||||
v-model="skipSponsor"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipIntro">
|
||||
<strong v-t="'actions.skip_intro'" />
|
||||
<input id="chkSkipIntro" v-model="skipIntro" class="checkbox" type="checkbox" @change="onChange($event)" />
|
||||
</label>
|
||||
<label class="pref" for="chkSkipOutro">
|
||||
<strong v-t="'actions.skip_outro'" />
|
||||
<input id="chkSkipOutro" v-model="skipOutro" class="checkbox" type="checkbox" @change="onChange($event)" />
|
||||
</label>
|
||||
<label class="pref" for="chkSkipPreview">
|
||||
<strong v-t="'actions.skip_preview'" />
|
||||
<input
|
||||
id="chkSkipPreview"
|
||||
v-model="skipPreview"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipInteraction">
|
||||
<strong v-t="'actions.skip_interaction'" />
|
||||
<input
|
||||
id="chkSkipInteraction"
|
||||
v-model="skipInteraction"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipSelfPromo">
|
||||
<strong v-t="'actions.skip_self_promo'" />
|
||||
<input
|
||||
id="chkSkipSelfPromo"
|
||||
v-model="skipSelfPromo"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipNonMusic">
|
||||
<strong v-t="'actions.skip_non_music'" />
|
||||
<input
|
||||
id="chkSkipNonMusic"
|
||||
v-model="skipMusicOffTopic"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipHighlight">
|
||||
<strong v-t="'actions.skip_highlight'" />
|
||||
<input
|
||||
id="chkSkipHighlight"
|
||||
v-model="skipHighlight"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="chkSkipFiller">
|
||||
<strong v-t="'actions.skip_filler_tangent'" />
|
||||
<input
|
||||
id="chkSkipFiller"
|
||||
v-model="skipFiller"
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
<label v-for="[name, item] in skipOptions" class="pref" :for="'ddlSkip_' + name" :key="name">
|
||||
<strong v-t="item.label" />
|
||||
<select :id="'ddlSkip_' + name" v-model="item.value" class="select w-auto" @change="onChange($event)">
|
||||
<option v-t="'actions.no'" value="no" />
|
||||
<option v-t="'actions.skip_button_only'" value="button" />
|
||||
<option v-t="'actions.skip_automatically'" value="auto" />
|
||||
</select>
|
||||
</label>
|
||||
<label class="pref" for="chkShowMarkers">
|
||||
<strong v-t="'actions.show_markers'" />
|
||||
|
@ -272,6 +202,16 @@
|
|||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
<label class="pref" for="txtMinSegmentLength">
|
||||
<strong v-t="'actions.min_segment_length'" />
|
||||
<input
|
||||
id="txtMinSegmentLength"
|
||||
v-model="minSegmentLength"
|
||||
class="input w-24"
|
||||
type="text"
|
||||
@change="onChange($event)"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<h2 class="text-center" v-t="'titles.instance'" />
|
||||
<label class="pref" for="ddlInstanceSelection">
|
||||
|
@ -391,16 +331,19 @@ export default {
|
|||
selectedAuthInstance: null,
|
||||
instances: [],
|
||||
sponsorBlock: true,
|
||||
skipSponsor: true,
|
||||
skipIntro: false,
|
||||
skipOutro: false,
|
||||
skipPreview: false,
|
||||
skipInteraction: true,
|
||||
skipSelfPromo: true,
|
||||
skipMusicOffTopic: true,
|
||||
skipHighlight: false,
|
||||
skipFiller: false,
|
||||
skipOptions: new Map([
|
||||
["sponsor", { value: "auto", label: "actions.skip_sponsors" }],
|
||||
["intro", { value: "no", label: "actions.skip_intro" }],
|
||||
["outro", { value: "no", label: "actions.skip_outro" }],
|
||||
["preview", { value: "no", label: "actions.skip_preview" }],
|
||||
["interaction", { value: "auto", label: "actions.skip_interaction" }],
|
||||
["selfpromo", { value: "auto", label: "actions.skip_self_promo" }],
|
||||
["music_offtopic", { value: "auto", label: "actions.skip_non_music" }],
|
||||
["poi_highlight", { value: "no", label: "actions.skip_highlight" }],
|
||||
["filler", { value: "no", label: "actions.skip_filler_tangent" }],
|
||||
]),
|
||||
showMarkers: true,
|
||||
minSegmentLength: 0,
|
||||
selectedTheme: "dark",
|
||||
autoPlayVideo: true,
|
||||
listen: false,
|
||||
|
@ -497,55 +440,25 @@ export default {
|
|||
this.selectedAuthInstance = this.getPreferenceString("auth_instance_url", this.selectedInstance);
|
||||
|
||||
this.sponsorBlock = this.getPreferenceBoolean("sponsorblock", true);
|
||||
if (localStorage.getItem("selectedSkip") !== null) {
|
||||
var skipList = localStorage.getItem("selectedSkip").split(",");
|
||||
this.skipSponsor =
|
||||
this.skipIntro =
|
||||
this.skipOutro =
|
||||
this.skipPreview =
|
||||
this.skipInteraction =
|
||||
this.skipSelfPromo =
|
||||
this.skipMusicOffTopic =
|
||||
this.skipHighlight =
|
||||
this.skipFiller =
|
||||
false;
|
||||
var skipOptions, skipList;
|
||||
if ((skipOptions = this.getPreferenceJSON("skipOptions")) !== undefined) {
|
||||
Object.entries(skipOptions).forEach(([key, value]) => {
|
||||
var opt = this.skipOptions.get(key);
|
||||
if (opt !== undefined) opt.value = value;
|
||||
else console.log("Unknown sponsor type: " + key);
|
||||
});
|
||||
} else if ((skipList = this.getPreferenceString("selectedSkip")) !== undefined) {
|
||||
skipList = skipList.split(",");
|
||||
this.skipOptions.forEach(opt => (opt.value = "no"));
|
||||
skipList.forEach(skip => {
|
||||
switch (skip) {
|
||||
case "sponsor":
|
||||
this.skipSponsor = true;
|
||||
break;
|
||||
case "intro":
|
||||
this.skipIntro = true;
|
||||
break;
|
||||
case "outro":
|
||||
this.skipOutro = true;
|
||||
break;
|
||||
case "preview":
|
||||
this.skipPreview = true;
|
||||
break;
|
||||
case "interaction":
|
||||
this.skipInteraction = true;
|
||||
break;
|
||||
case "selfpromo":
|
||||
this.skipSelfPromo = true;
|
||||
break;
|
||||
case "music_offtopic":
|
||||
this.skipMusicOffTopic = true;
|
||||
break;
|
||||
case "poi_highlight":
|
||||
this.skipHighlight = true;
|
||||
break;
|
||||
case "filler":
|
||||
this.skipFiller = true;
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown sponsor type: " + skip);
|
||||
break;
|
||||
}
|
||||
var opt = this.skipOptions.get(skip);
|
||||
if (opt !== undefined) opt.value = "auto";
|
||||
else console.log("Unknown sponsor type: " + skip);
|
||||
});
|
||||
}
|
||||
|
||||
this.showMarkers = this.getPreferenceBoolean("showMarkers", true);
|
||||
this.minSegmentLength = Math.max(this.getPreferenceNumber("minSegmentLength", 0), 0);
|
||||
this.selectedTheme = this.getPreferenceString("theme", "dark");
|
||||
this.autoPlayVideo = this.getPreferenceBoolean("playerAutoPlay", true);
|
||||
this.listen = this.getPreferenceBoolean("listen", false);
|
||||
|
@ -594,19 +507,12 @@ export default {
|
|||
localStorage.setItem("auth_instance_url", this.selectedAuthInstance);
|
||||
localStorage.setItem("sponsorblock", this.sponsorBlock);
|
||||
|
||||
var sponsorSelected = [];
|
||||
if (this.skipSponsor) sponsorSelected.push("sponsor");
|
||||
if (this.skipIntro) sponsorSelected.push("intro");
|
||||
if (this.skipOutro) sponsorSelected.push("outro");
|
||||
if (this.skipPreview) sponsorSelected.push("preview");
|
||||
if (this.skipInteraction) sponsorSelected.push("interaction");
|
||||
if (this.skipSelfPromo) sponsorSelected.push("selfpromo");
|
||||
if (this.skipMusicOffTopic) sponsorSelected.push("music_offtopic");
|
||||
if (this.skipHighlight) sponsorSelected.push("poi_highlight");
|
||||
if (this.skipFiller) sponsorSelected.push("filler");
|
||||
localStorage.setItem("selectedSkip", sponsorSelected);
|
||||
var skipOptions = {};
|
||||
this.skipOptions.forEach((v, k) => (skipOptions[k] = v.value));
|
||||
localStorage.setItem("skipOptions", JSON.stringify(skipOptions));
|
||||
|
||||
localStorage.setItem("showMarkers", this.showMarkers);
|
||||
localStorage.setItem("minSegmentLength", this.minSegmentLength);
|
||||
localStorage.setItem("theme", this.selectedTheme);
|
||||
localStorage.setItem("playerAutoPlay", this.autoPlayVideo);
|
||||
localStorage.setItem("listen", this.listen);
|
||||
|
|
|
@ -6,6 +6,17 @@
|
|||
:class="{ 'player-container': !isEmbed }"
|
||||
>
|
||||
<video ref="videoEl" class="w-full" data-shaka-player :autoplay="shouldAutoPlay" :loop="selectedAutoLoop" />
|
||||
<button
|
||||
v-if="inSegment"
|
||||
class="skip-segment-button"
|
||||
type="button"
|
||||
:aria-label="$t('actions.skip_segment')"
|
||||
aria-pressed="false"
|
||||
@click="onClickSkipSegment"
|
||||
>
|
||||
<span v-t="'actions.skip_segment'" />
|
||||
<i class="material-icons-round">skip_next</i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -51,6 +62,7 @@ export default {
|
|||
lastUpdate: new Date().getTime(),
|
||||
initialSeekComplete: false,
|
||||
destroying: false,
|
||||
inSegment: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -88,7 +100,7 @@ export default {
|
|||
this.hotkeysPromise.then(() => {
|
||||
var self = this;
|
||||
this.$hotkeys(
|
||||
"f,m,j,k,l,c,space,up,down,left,right,0,1,2,3,4,5,6,7,8,9,shift+n,shift+,,shift+.",
|
||||
"f,m,j,k,l,c,space,up,down,left,right,0,1,2,3,4,5,6,7,8,9,shift+n,shift+,,shift+.,return",
|
||||
function (e, handler) {
|
||||
const videoEl = self.$refs.videoEl;
|
||||
switch (handler.key) {
|
||||
|
@ -184,6 +196,9 @@ export default {
|
|||
case "shift+.":
|
||||
self.$player.trickPlay(Math.min(videoEl.playbackRate + 0.25, 2));
|
||||
break;
|
||||
case "return":
|
||||
self.skipSegment(videoEl);
|
||||
break;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -361,17 +376,11 @@ export default {
|
|||
this.$emit("timeupdate", time);
|
||||
this.updateProgressDatabase(time);
|
||||
if (this.sponsors && this.sponsors.segments) {
|
||||
this.sponsors.segments.map(segment => {
|
||||
if (!segment.skipped || this.selectedAutoLoop) {
|
||||
const end = segment.segment[1];
|
||||
if (time >= segment.segment[0] && time < end) {
|
||||
console.log("Skipped segment at " + time);
|
||||
videoEl.currentTime = end;
|
||||
segment.skipped = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
const segment = this.findCurrentSegment(time);
|
||||
this.inSegment = !!segment;
|
||||
if (segment?.autoskip && (!segment.skipped || this.selectedAutoLoop)) {
|
||||
this.skipSegment(videoEl, segment);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -398,6 +407,21 @@ export default {
|
|||
|
||||
//TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
|
||||
},
|
||||
findCurrentSegment(time) {
|
||||
return this.sponsors?.segments?.find(s => time >= s.segment[0] && time < s.segment[1]);
|
||||
},
|
||||
onClickSkipSegment() {
|
||||
const videoEl = this.$refs.videoEl;
|
||||
this.skipSegment(videoEl);
|
||||
},
|
||||
skipSegment(videoEl, segment) {
|
||||
const time = videoEl.currentTime;
|
||||
if (!segment) segment = this.findCurrentSegment(time);
|
||||
if (!segment) return;
|
||||
console.log("Skipped segment at " + time);
|
||||
videoEl.currentTime = segment.segment[1];
|
||||
segment.skipped = true;
|
||||
},
|
||||
setPlayerAttrs(localPlayer, videoEl, uri, mime, shaka) {
|
||||
const url = "/watch?v=" + this.video.id;
|
||||
|
||||
|
@ -678,6 +702,11 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
sponsors() {
|
||||
const skipOptions = this.getPreferenceJSON("skipOptions", {});
|
||||
this.sponsors?.segments?.forEach(segment => {
|
||||
const option = skipOptions[segment.category];
|
||||
segment.autoskip = option === undefined || option === "auto";
|
||||
});
|
||||
if (this.getPreferenceBoolean("showMarkers", true)) {
|
||||
this.shakaPromise.then(() => {
|
||||
this.updateMarkers();
|
||||
|
@ -719,4 +748,34 @@ export default {
|
|||
background-color: rgba(0, 0, 0, 0.6) !important;
|
||||
padding: 0.09em 0;
|
||||
}
|
||||
|
||||
.skip-segment-button {
|
||||
/* position button above player overlay */
|
||||
z-index: 1000;
|
||||
|
||||
position: absolute;
|
||||
transform: translate(0, -50%);
|
||||
top: 50%;
|
||||
right: 0;
|
||||
|
||||
background-color: rgb(0 0 0 / 0.5);
|
||||
border: 2px rgba(255, 255, 255, 0.75) solid;
|
||||
border-right: 0;
|
||||
border-radius: 0.75em;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
padding: 0.5em;
|
||||
|
||||
/* center text vertically */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.skip-segment-button .material-icons-round {
|
||||
font-size: 1.6em !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -367,15 +367,28 @@ export default {
|
|||
return this.fetchJson(this.apiUrl() + "/streams/" + this.getVideoId());
|
||||
},
|
||||
async fetchSponsors() {
|
||||
return await this.fetchJson(this.apiUrl() + "/sponsors/" + this.getVideoId(), {
|
||||
category:
|
||||
'["' +
|
||||
this.getPreferenceString("selectedSkip", "sponsor,interaction,selfpromo,music_offtopic").replaceAll(
|
||||
",",
|
||||
'","',
|
||||
) +
|
||||
'"]',
|
||||
var selectedSkip = this.getPreferenceString(
|
||||
"selectedSkip",
|
||||
"sponsor,interaction,selfpromo,music_offtopic",
|
||||
).split(",");
|
||||
const skipOptions = this.getPreferenceJSON("skipOptions");
|
||||
if (skipOptions !== undefined) {
|
||||
selectedSkip = Object.keys(skipOptions).filter(
|
||||
k => skipOptions[k] !== undefined && skipOptions[k] !== "no",
|
||||
);
|
||||
}
|
||||
|
||||
const sponsors = await this.fetchJson(this.apiUrl() + "/sponsors/" + this.getVideoId(), {
|
||||
category: JSON.stringify(selectedSkip),
|
||||
});
|
||||
|
||||
const minSegmentLength = Math.max(this.getPreferenceNumber("minSegmentLength", 0), 0);
|
||||
sponsors.segments = sponsors.segments.filter(segment => {
|
||||
const length = segment.segment[1] - segment.segment[0];
|
||||
return length >= minSegmentLength;
|
||||
});
|
||||
|
||||
return sponsors;
|
||||
},
|
||||
toggleComments() {
|
||||
this.showComments = !this.showComments;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
"back": "Back",
|
||||
"uses_api_from": "Uses the API from ",
|
||||
"enable_sponsorblock": "Enable Sponsorblock",
|
||||
"skip_button_only": "Show skip button",
|
||||
"skip_automatically": "Automatically",
|
||||
"skip_sponsors": "Skip Sponsors",
|
||||
"skip_intro": "Skip Intermission/Intro Animation",
|
||||
"skip_outro": "Skip Endcards/Credits",
|
||||
|
@ -40,6 +42,8 @@
|
|||
"skip_highlight": "Skip Highlight",
|
||||
"skip_filler_tangent": "Skip Filler Tangent",
|
||||
"show_markers": "Show Markers on Player",
|
||||
"min_segment_length": "Minimum Segment Length (in seconds)",
|
||||
"skip_segment": "Skip Segment",
|
||||
"theme": "Theme",
|
||||
"auto": "Auto",
|
||||
"dark": "Dark",
|
||||
|
|
|
@ -162,6 +162,15 @@ const mixin = {
|
|||
return Number(value);
|
||||
} else return defaultVal;
|
||||
},
|
||||
getPreferenceJSON(key, defaultVal) {
|
||||
var value;
|
||||
if (
|
||||
(value = new URLSearchParams(window.location.search).get(key)) !== null ||
|
||||
(this.testLocalStorage && (value = localStorage.getItem(key)) !== null)
|
||||
) {
|
||||
return JSON.parse(value);
|
||||
} else return defaultVal;
|
||||
},
|
||||
apiUrl() {
|
||||
return this.getPreferenceString("instance", "https://pipedapi.kavin.rocks");
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue