mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-06 19:47:04 +03:00
Added the possibility to loop a chapter
This commit is contained in:
4
public/icons/loop.svg
Normal file
4
public/icons/loop.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#FFFFFF">
|
||||||
|
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-8 4-8 7h2s1-5 6-5c1.66 0 3.14.69 4.22 1.78L14 10h6V4l-2.35 2.35z"/>
|
||||||
|
<path d="M5.85 17.65C7.3 19.1 9.29 20 11.5 20c4.42 0 8-4 8-7h-2s-1 5-6 5c-1.66 0-3.14-.69-4.22-1.78L9.5 14h-6v6z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 335 B |
4
public/icons/looped.svg
Normal file
4
public/icons/looped.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#80fff6">
|
||||||
|
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-8 4-8 7h2s1-5 6-5c1.66 0 3.14.69 4.22 1.78L14 10h6V4l-2.35 2.35z"/>
|
||||||
|
<path d="M5.85 17.65C7.3 19.1 9.29 20 11.5 20c4.42 0 8-4 8-7h-2s-1 5-6 5c-1.66 0-3.14-.69-4.22-1.78L9.5 14h-6v6z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 334 B |
@@ -76,6 +76,7 @@ let sponsorTimes: SponsorTime[] = [];
|
|||||||
let existingChaptersImported = false;
|
let existingChaptersImported = false;
|
||||||
let importingChaptersWaitingForFocus = false;
|
let importingChaptersWaitingForFocus = false;
|
||||||
let importingChaptersWaiting = false;
|
let importingChaptersWaiting = false;
|
||||||
|
let loopedChapter :SponsorTime = null;
|
||||||
// List of open skip notices
|
// List of open skip notices
|
||||||
const skipNotices: SkipNotice[] = [];
|
const skipNotices: SkipNotice[] = [];
|
||||||
let upcomingNotice: UpcomingNotice | null = null;
|
let upcomingNotice: UpcomingNotice | null = null;
|
||||||
@@ -301,6 +302,20 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
|||||||
case "copyToClipboard":
|
case "copyToClipboard":
|
||||||
navigator.clipboard.writeText(request.text);
|
navigator.clipboard.writeText(request.text);
|
||||||
break;
|
break;
|
||||||
|
case "loopChapter":
|
||||||
|
if (!request.UUID){
|
||||||
|
loopedChapter = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loopedChapter = {...utils.getSponsorTimeFromUUID(sponsorTimes, request.UUID)};
|
||||||
|
loopedChapter.actionType = ActionType.Skip;
|
||||||
|
loopedChapter.segment = [loopedChapter.segment[1], loopedChapter.segment[0]];
|
||||||
|
break;
|
||||||
|
case "getLoopedChapter":
|
||||||
|
sendResponse({
|
||||||
|
UUID: loopedChapter?.UUID,
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "importSegments": {
|
case "importSegments": {
|
||||||
const importedSegments = importTimes(request.data, getVideoDuration());
|
const importedSegments = importTimes(request.data, getVideoDuration());
|
||||||
let addedSegments = false;
|
let addedSegments = false;
|
||||||
@@ -397,6 +412,7 @@ function resetValues() {
|
|||||||
sponsorTimes = [];
|
sponsorTimes = [];
|
||||||
existingChaptersImported = false;
|
existingChaptersImported = false;
|
||||||
sponsorSkipped = [];
|
sponsorSkipped = [];
|
||||||
|
loopedChapter = null;
|
||||||
lastResponseStatus = 0;
|
lastResponseStatus = 0;
|
||||||
shownSegmentFailedToFetchWarning = false;
|
shownSegmentFailedToFetchWarning = false;
|
||||||
|
|
||||||
@@ -694,7 +710,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
|
|||||||
for (const segment of skipInfo.array) {
|
for (const segment of skipInfo.array) {
|
||||||
if (shouldAutoSkip(segment) &&
|
if (shouldAutoSkip(segment) &&
|
||||||
segment.segment[0] >= skipTime[0] && segment.segment[1] <= skipTime[1]
|
segment.segment[0] >= skipTime[0] && segment.segment[1] <= skipTime[1]
|
||||||
&& segment.segment[0] === segment.scheduledTime) { // Don't include artifical scheduled segments (end times for mutes)
|
&& segment.segment[0] === segment.scheduledTime) { // Don't include artificial scheduled segments (end times for mutes)
|
||||||
skippingSegments.push(segment);
|
skippingSegments.push(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +727,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
|
|||||||
forceVideoTime ||= Math.max(getCurrentTime(), getVirtualTime());
|
forceVideoTime ||= Math.max(getCurrentTime(), getVirtualTime());
|
||||||
|
|
||||||
if ((shouldSkip(currentSkip) || sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment))) {
|
if ((shouldSkip(currentSkip) || sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment))) {
|
||||||
if (forceVideoTime >= skipTime[0] - skipBuffer && forceVideoTime < skipTime[1]) {
|
if (forceVideoTime >= skipTime[0] - skipBuffer && (forceVideoTime < skipTime[1] || skipTime[1] < skipTime[0])) {
|
||||||
skipToTime({
|
skipToTime({
|
||||||
v: getVideo(),
|
v: getVideo(),
|
||||||
skipTime,
|
skipTime,
|
||||||
@@ -719,7 +735,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
|
|||||||
openNotice: skipInfo.openNotice
|
openNotice: skipInfo.openNotice
|
||||||
});
|
});
|
||||||
|
|
||||||
// These are segments that start at the exact same time but need seperate notices
|
// These are segments that start at the exact same time but need separate notices
|
||||||
for (const extra of skipInfo.extraIndexes) {
|
for (const extra of skipInfo.extraIndexes) {
|
||||||
const extraSkip = skipInfo.array[extra];
|
const extraSkip = skipInfo.array[extra];
|
||||||
if (shouldSkip(extraSkip)) {
|
if (shouldSkip(extraSkip)) {
|
||||||
@@ -752,7 +768,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't pretend to be earlier than we are, could result in loops
|
// Don't pretend to be earlier than we are, could result in loops
|
||||||
if (forcedSkipTime !== null && forceVideoTime > forcedSkipTime) {
|
if (forcedSkipTime !== null && forceVideoTime > forcedSkipTime && skipTime[1] > skipTime[0]) {
|
||||||
forcedSkipTime = forceVideoTime;
|
forcedSkipTime = forceVideoTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -867,7 +883,8 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
|
|||||||
const recordedVideoID = videoID || getVideoID();
|
const recordedVideoID = videoID || getVideoID();
|
||||||
if (currentVideoID !== recordedVideoID || (sponsorTime
|
if (currentVideoID !== recordedVideoID || (sponsorTime
|
||||||
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))
|
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))
|
||||||
&& !sponsorTimesSubmitting.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))) {
|
&& !sponsorTimesSubmitting.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1])
|
||||||
|
&& (!isLoopedChapter(sponsorTime)))) {
|
||||||
// Something has really gone wrong
|
// Something has really gone wrong
|
||||||
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
|
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
|
||||||
console.error("[SponsorBlock] VideoID recorded: " + recordedVideoID + ". Actual VideoID: " + currentVideoID);
|
console.error("[SponsorBlock] VideoID recorded: " + recordedVideoID + ". Actual VideoID: " + currentVideoID);
|
||||||
@@ -1537,7 +1554,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
|
|||||||
array: submittedArray,
|
array: submittedArray,
|
||||||
index: minSponsorTimeIndex,
|
index: minSponsorTimeIndex,
|
||||||
endIndex: endTimeIndex,
|
endIndex: endTimeIndex,
|
||||||
extraIndexes, // Segments at same time that need seperate notices
|
extraIndexes, // Segments at same time that need separate notices
|
||||||
openNotice: true
|
openNotice: true
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -1572,8 +1589,16 @@ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideH
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to the normal endTime
|
let latestEndTimeIndex;
|
||||||
let latestEndTimeIndex = index;
|
// Default to looped chapter if its end would have been skipped
|
||||||
|
if (loopedChapter
|
||||||
|
&& (loopedChapter.segment[0] > sponsorTimes[index].segment[0]
|
||||||
|
&& loopedChapter.segment[0] <= sponsorTimes[index]?.segment[1])){
|
||||||
|
latestEndTimeIndex = sponsorTimes.length - 1;
|
||||||
|
} else {
|
||||||
|
// or the normal end time otherwise
|
||||||
|
latestEndTimeIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < sponsorTimes?.length; i++) {
|
for (let i = 0; i < sponsorTimes?.length; i++) {
|
||||||
const currentSegment = sponsorTimes[i].segment;
|
const currentSegment = sponsorTimes[i].segment;
|
||||||
@@ -1616,7 +1641,8 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments:
|
|||||||
const shouldIncludeTime = (segment: ScheduledTime ) => (minimum === undefined
|
const shouldIncludeTime = (segment: ScheduledTime ) => (minimum === undefined
|
||||||
|| ((includeNonIntersectingSegments && segment.scheduledTime >= minimum)
|
|| ((includeNonIntersectingSegments && segment.scheduledTime >= minimum)
|
||||||
|| (includeIntersectingSegments && segment.scheduledTime < minimum
|
|| (includeIntersectingSegments && segment.scheduledTime < minimum
|
||||||
&& segment.segment[1] > minimum && shouldSkip(segment)))) // Only include intersecting skippable segments
|
&& ((segment.segment[1] > minimum && shouldSkip(segment)) // Only include intersecting skippable segments
|
||||||
|
|| isLoopedChapter(segment)))))
|
||||||
&& (!hideHiddenSponsors || segment.hidden === SponsorHideType.Visible)
|
&& (!hideHiddenSponsors || segment.hidden === SponsorHideType.Visible)
|
||||||
&& segment.segment.length === 2
|
&& segment.segment.length === 2
|
||||||
&& segment.actionType !== ActionType.Poi
|
&& segment.actionType !== ActionType.Poi
|
||||||
@@ -1638,6 +1664,12 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (loopedChapter){
|
||||||
|
possibleTimes.push({
|
||||||
|
...loopedChapter,
|
||||||
|
scheduledTime: loopedChapter.segment[0]})
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < possibleTimes.length; i++) {
|
for (let i = 0; i < possibleTimes.length; i++) {
|
||||||
if (shouldIncludeTime(possibleTimes[i])) {
|
if (shouldIncludeTime(possibleTimes[i])) {
|
||||||
scheduledTimes.push(possibleTimes[i].scheduledTime);
|
scheduledTimes.push(possibleTimes[i].scheduledTime);
|
||||||
@@ -1895,7 +1927,8 @@ function shouldAutoSkip(segment: SponsorTime): boolean {
|
|||||||
&& (utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
|
&& (utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
|
||||||
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
|
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
|
||||||
&& segment.actionType === ActionType.Skip)
|
&& segment.actionType === ActionType.Skip)
|
||||||
|| sponsorTimesSubmitting.some((s) => s.segment === segment.segment));
|
|| sponsorTimesSubmitting.some((s) => s.segment === segment.segment))
|
||||||
|
|| isLoopedChapter(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldSkip(segment: SponsorTime): boolean {
|
function shouldSkip(segment: SponsorTime): boolean {
|
||||||
@@ -1903,7 +1936,13 @@ function shouldSkip(segment: SponsorTime): boolean {
|
|||||||
&& segment.source !== SponsorSourceType.YouTube
|
&& segment.source !== SponsorSourceType.YouTube
|
||||||
&& utils.getCategorySelection(segment.category)?.option !== CategorySkipOption.ShowOverlay)
|
&& utils.getCategorySelection(segment.category)?.option !== CategorySkipOption.ShowOverlay)
|
||||||
|| (Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
|
|| (Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
|
||||||
&& segment.actionType === ActionType.Skip);
|
&& segment.actionType === ActionType.Skip)
|
||||||
|
|| isLoopedChapter(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLoopedChapter(segment: SponsorTime) :boolean{
|
||||||
|
return !!segment && !!loopedChapter && segment.actionType === ActionType.Skip && segment.segment[1] != undefined
|
||||||
|
&& segment.segment[0] === loopedChapter.segment[0] && segment.segment[1] === loopedChapter.segment[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates any missing buttons on the YouTube player if possible. */
|
/** Creates any missing buttons on the YouTube player if possible. */
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ interface DefaultMessage {
|
|||||||
| "submitTimes"
|
| "submitTimes"
|
||||||
| "refreshSegments"
|
| "refreshSegments"
|
||||||
| "closePopup"
|
| "closePopup"
|
||||||
| "getLogs";
|
| "getLogs"
|
||||||
|
| "getLoopedChapter";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BoolValueMessage {
|
interface BoolValueMessage {
|
||||||
@@ -58,6 +59,11 @@ interface ImportSegmentsMessage {
|
|||||||
data: string;
|
data: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LoopChapterMessage {
|
||||||
|
message: "loopChapter";
|
||||||
|
UUID: SegmentUUID;
|
||||||
|
}
|
||||||
|
|
||||||
interface KeyDownMessage {
|
interface KeyDownMessage {
|
||||||
message: "keydown";
|
message: "keydown";
|
||||||
key: string;
|
key: string;
|
||||||
@@ -70,7 +76,7 @@ interface KeyDownMessage {
|
|||||||
metaKey: boolean;
|
metaKey: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoFoundMessage | SkipMessage | SubmitVoteMessage | HideSegmentMessage | CopyToClipboardMessage | ImportSegmentsMessage | KeyDownMessage);
|
export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoFoundMessage | SkipMessage | SubmitVoteMessage | HideSegmentMessage | CopyToClipboardMessage | ImportSegmentsMessage | KeyDownMessage | LoopChapterMessage);
|
||||||
|
|
||||||
export interface IsInfoFoundMessageResponse {
|
export interface IsInfoFoundMessageResponse {
|
||||||
found: boolean;
|
found: boolean;
|
||||||
@@ -97,6 +103,10 @@ export interface IsChannelWhitelistedResponse {
|
|||||||
value: boolean;
|
value: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LoopedChapterResponse {
|
||||||
|
UUID: SegmentUUID;
|
||||||
|
}
|
||||||
|
|
||||||
export type MessageResponse =
|
export type MessageResponse =
|
||||||
IsInfoFoundMessageResponse
|
IsInfoFoundMessageResponse
|
||||||
| GetVideoIdResponse
|
| GetVideoIdResponse
|
||||||
@@ -107,7 +117,8 @@ export type MessageResponse =
|
|||||||
| VoteResponse
|
| VoteResponse
|
||||||
| ImportSegmentsResponse
|
| ImportSegmentsResponse
|
||||||
| RefreshSegmentsResponse
|
| RefreshSegmentsResponse
|
||||||
| LogResponse;
|
| LogResponse
|
||||||
|
| LoopedChapterResponse;
|
||||||
|
|
||||||
export interface VoteResponse {
|
export interface VoteResponse {
|
||||||
successType: number;
|
successType: number;
|
||||||
|
|||||||
40
src/popup.ts
40
src/popup.ts
@@ -13,6 +13,7 @@ import {
|
|||||||
IsChannelWhitelistedResponse,
|
IsChannelWhitelistedResponse,
|
||||||
IsInfoFoundMessageResponse,
|
IsInfoFoundMessageResponse,
|
||||||
LogResponse,
|
LogResponse,
|
||||||
|
LoopedChapterResponse,
|
||||||
Message,
|
Message,
|
||||||
MessageResponse,
|
MessageResponse,
|
||||||
PopupMessage,
|
PopupMessage,
|
||||||
@@ -539,7 +540,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//display the video times from the array at the top, in a different section
|
//display the video times from the array at the top, in a different section
|
||||||
function displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], time: number) {
|
async function displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], time: number) {
|
||||||
let currentSegmentTab = segmentTab;
|
let currentSegmentTab = segmentTab;
|
||||||
if (!sponsorTimes.some((segment) => segment.actionType === ActionType.Chapter && segment.source !== SponsorSourceType.YouTube)) {
|
if (!sponsorTimes.some((segment) => segment.actionType === ActionType.Chapter && segment.source !== SponsorSourceType.YouTube)) {
|
||||||
PageElements.issueReporterTabs.classList.add("hidden");
|
PageElements.issueReporterTabs.classList.add("hidden");
|
||||||
@@ -554,6 +555,9 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const response = await sendTabMessageAsync({message : "getLoopedChapter"}) as LoopedChapterResponse
|
||||||
|
const loopedChapter = response.UUID;
|
||||||
|
|
||||||
// Sort list by start time
|
// Sort list by start time
|
||||||
const downloadedTimes = sponsorTimes
|
const downloadedTimes = sponsorTimes
|
||||||
.filter((segment) => {
|
.filter((segment) => {
|
||||||
@@ -728,6 +732,37 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loopButton = document.createElement("input");
|
||||||
|
const loopButtonIcon = document.createElement("img");
|
||||||
|
loopButtonIcon.src = loopedChapter === UUID ? chrome.runtime.getURL("icons/looped.svg") : chrome.runtime.getURL("icons/loop.svg");
|
||||||
|
loopButtonIcon.className = "loopButtonIcon";
|
||||||
|
loopButton.type = "checkbox";
|
||||||
|
loopButton.checked = loopedChapter === UUID;
|
||||||
|
loopButton.id = "loopChapterButtonContainer" + UUID;
|
||||||
|
loopButton.className = "loopButton hidden";
|
||||||
|
|
||||||
|
loopButton.addEventListener("click", () => {
|
||||||
|
const stopAnimation = AnimationUtils.applyLoadingAnimation(loopButtonIcon, 0.4);
|
||||||
|
stopAnimation();
|
||||||
|
if (loopButton.checked) {
|
||||||
|
document.querySelectorAll(".loopButton").forEach((e :HTMLInputElement) => e.checked = false);
|
||||||
|
document.querySelectorAll(".loopButtonIcon").forEach((e :HTMLImageElement) => e.src = chrome.runtime.getURL("icons/loop.svg"));
|
||||||
|
sendTabMessage({message: "loopChapter", UUID : UUID})
|
||||||
|
loopButton.checked = true;
|
||||||
|
} else {
|
||||||
|
sendTabMessage({message: "loopChapter", UUID : null})
|
||||||
|
loopButton.checked = false;
|
||||||
|
}
|
||||||
|
loopButtonIcon.src = loopButton.checked ? chrome.runtime.getURL("icons/looped.svg") : chrome.runtime.getURL("icons/loop.svg");
|
||||||
|
loopButtonLabel.title = loopButton.checked ? chrome.i18n.getMessage("unloopChapter") : chrome.i18n.getMessage("loopChapter");
|
||||||
|
});
|
||||||
|
const loopButtonLabel = document.createElement("label");
|
||||||
|
loopButtonLabel.setAttribute("for", loopButton.id);
|
||||||
|
loopButtonLabel.className = "voteButton";
|
||||||
|
loopButtonLabel.title = loopedChapter === UUID ? chrome.i18n.getMessage("unloopChapter") : chrome.i18n.getMessage("loopChapter");
|
||||||
|
loopButtonLabel.appendChild(loopButtonIcon);
|
||||||
|
loopButtonLabel.appendChild(loopButton);
|
||||||
|
|
||||||
const skipButton = document.createElement("img");
|
const skipButton = document.createElement("img");
|
||||||
skipButton.id = "sponsorTimesSkipButtonContainer" + UUID;
|
skipButton.id = "sponsorTimesSkipButtonContainer" + UUID;
|
||||||
skipButton.className = "voteButton";
|
skipButton.className = "voteButton";
|
||||||
@@ -743,6 +778,9 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
voteButtonsContainer.appendChild(upvoteButton);
|
voteButtonsContainer.appendChild(upvoteButton);
|
||||||
voteButtonsContainer.appendChild(downvoteButton);
|
voteButtonsContainer.appendChild(downvoteButton);
|
||||||
voteButtonsContainer.appendChild(uuidButton);
|
voteButtonsContainer.appendChild(uuidButton);
|
||||||
|
if (downloadedTimes[i].actionType === ActionType.Chapter) {
|
||||||
|
voteButtonsContainer.appendChild(loopButtonLabel);
|
||||||
|
}
|
||||||
if (downloadedTimes[i].actionType === ActionType.Skip || downloadedTimes[i].actionType === ActionType.Mute
|
if (downloadedTimes[i].actionType === ActionType.Skip || downloadedTimes[i].actionType === ActionType.Mute
|
||||||
|| downloadedTimes[i].actionType === ActionType.Poi
|
|| downloadedTimes[i].actionType === ActionType.Poi
|
||||||
&& [SponsorHideType.Visible, SponsorHideType.Hidden].includes(downloadedTimes[i].hidden)) {
|
&& [SponsorHideType.Visible, SponsorHideType.Hidden].includes(downloadedTimes[i].hidden)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user