mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-06 19:47:04 +03:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15fcc971f6 | ||
|
|
32adbb9581 | ||
|
|
4ecd02510b | ||
|
|
0dbb6474b8 | ||
|
|
c974c2a6d6 | ||
|
|
a6695254b6 | ||
|
|
e8a82eddca | ||
|
|
d3684dbedd | ||
|
|
6c9a403731 | ||
|
|
3be51c89a9 | ||
|
|
5b845a56e1 | ||
|
|
7b572c3c0e | ||
|
|
56bb22d03d | ||
|
|
e1d656f43f | ||
|
|
e14b3c76f9 | ||
|
|
de830cda48 | ||
|
|
d8057fb547 | ||
|
|
2dd69d443b | ||
|
|
6732850b41 | ||
|
|
287233785e | ||
|
|
de094cb11f | ||
|
|
2307691044 | ||
|
|
2dca0d7526 | ||
|
|
a1505bcf20 | ||
|
|
25b53754ba | ||
|
|
6c71036356 | ||
|
|
f55f2606a7 | ||
|
|
e9b7abd219 | ||
|
|
63d3309605 | ||
|
|
b4615d7d79 | ||
|
|
ec7eee650b | ||
|
|
154bb1749d | ||
|
|
742eb7ef57 | ||
|
|
88526aa46e | ||
|
|
1909e66c87 | ||
|
|
ba92e6e386 | ||
|
|
bdbe8b60cc |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "5.5.6",
|
"version": "5.6",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"homepage_url": "https://sponsor.ajay.app",
|
"homepage_url": "https://sponsor.ajay.app",
|
||||||
|
|||||||
Submodule maze-utils updated: 9fbde12534...6212c29b9e
1238
package-lock.json
generated
1238
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@
|
|||||||
"ts-loader": "^9.4.2",
|
"ts-loader": "^9.4.2",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "4.9",
|
"typescript": "4.9",
|
||||||
"web-ext": "^7.6.2",
|
"web-ext": "^7.10.0",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-merge": "^5.8.0"
|
"webpack-merge": "^5.8.0"
|
||||||
|
|||||||
Submodule public/_locales updated: 3f17e35086...becf2e3f14
@@ -26,6 +26,11 @@
|
|||||||
transition: transform .1s cubic-bezier(0,0,0.2,1);
|
transition: transform .1s cubic-bezier(0,0,0.2,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* May 2024 hover preview */
|
||||||
|
.YtPlayerProgressBarProgressBar #previewbar {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
.ytp-big-mode #previewbar {
|
.ytp-big-mode #previewbar {
|
||||||
transform: scaleY(0.625) translateY(-30%) translateY(1.5px);
|
transform: scaleY(0.625) translateY(-30%) translateY(1.5px);
|
||||||
}
|
}
|
||||||
@@ -780,6 +785,18 @@ input::-webkit-inner-spin-button {
|
|||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Description on right layout */
|
||||||
|
#title > #categoryPillParent {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 2.8rem;
|
||||||
|
}
|
||||||
|
#title > #categoryPillParent > #categoryPill.cbPillOpen {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
#categoryPillParent {
|
#categoryPillParent {
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
|
|||||||
@@ -219,20 +219,22 @@
|
|||||||
__MSG_showSkipNotice__
|
__MSG_showSkipNotice__
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-type="selector" data-sync="noticeVisibilityMode" data-dependent-on="dontShowNotice">
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
|
||||||
|
|
||||||
|
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
|
||||||
|
<option value="0">__MSG_noticeVisibilityMode0__</option>
|
||||||
|
<option value="1">__MSG_noticeVisibilityMode1__</option>
|
||||||
|
<option value="2">__MSG_noticeVisibilityMode2__</option>
|
||||||
|
<option value="3">__MSG_noticeVisibilityMode3__</option>
|
||||||
|
<option value="4">__MSG_noticeVisibilityMode4__</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-type="selector" data-sync="noticeVisibilityMode">
|
|
||||||
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
|
|
||||||
|
|
||||||
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
|
|
||||||
<option value="0">__MSG_noticeVisibilityMode0__</option>
|
|
||||||
<option value="1">__MSG_noticeVisibilityMode1__</option>
|
|
||||||
<option value="2">__MSG_noticeVisibilityMode2__</option>
|
|
||||||
<option value="3">__MSG_noticeVisibilityMode3__</option>
|
|
||||||
<option value="4">__MSG_noticeVisibilityMode4__</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div data-type="toggle" data-sync="showCategoryGuidelines">
|
<div data-type="toggle" data-sync="showCategoryGuidelines">
|
||||||
<div class="switch-container">
|
<div class="switch-container">
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
@@ -634,7 +636,19 @@
|
|||||||
|
|
||||||
<div class="small-description">__MSG_whatTrackDownvotes__</div>
|
<div class="small-description">__MSG_whatTrackDownvotes__</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-type="toggle" data-sync="trackDownvotesInPrivate" data-confirm-on="false">
|
||||||
|
<div class="switch-container">
|
||||||
|
<label class="switch">
|
||||||
|
<input id="trackDownvotesInPrivate" type="checkbox" checked>
|
||||||
|
<span class="slider round"></span>
|
||||||
|
</label>
|
||||||
|
<label class="switch-label" for="trackDownvotesInPrivate">
|
||||||
|
__MSG_enableTrackDownvotesInPrivate__
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div data-type="button-press" data-sync="copyDebugInformation" data-confirm-message="copyDebugInformation">
|
<div data-type="button-press" data-sync="copyDebugInformation" data-confirm-message="copyDebugInformation">
|
||||||
<div class="option-button trigger-button">
|
<div class="option-button trigger-button">
|
||||||
__MSG_copyDebugInformation__
|
__MSG_copyDebugInformation__
|
||||||
|
|||||||
@@ -23,12 +23,14 @@ export interface CategoryPillState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryPillState> {
|
class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryPillState> {
|
||||||
|
mainRef: React.MutableRefObject<HTMLSpanElement>;
|
||||||
tooltip?: Tooltip;
|
tooltip?: Tooltip;
|
||||||
|
|
||||||
constructor(props: CategoryPillProps) {
|
constructor(props: CategoryPillProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.mainRef = React.createRef();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
segment: null,
|
segment: null,
|
||||||
show: false,
|
show: false,
|
||||||
@@ -43,13 +45,17 @@ class CategoryPillComponent extends React.Component<CategoryPillProps, CategoryP
|
|||||||
color: this.getTextColor(),
|
color: this.getTextColor(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To be able to remove the margin from the parent
|
||||||
|
this.mainRef?.current?.parentElement?.classList?.toggle("cbPillOpen", this.state.show);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span style={style}
|
<span style={style}
|
||||||
className={"sponsorBlockCategoryPill" + (!this.props.showTextByDefault ? " sbPillNoText" : "")}
|
className={"sponsorBlockCategoryPill" + (!this.props.showTextByDefault ? " sbPillNoText" : "")}
|
||||||
aria-label={this.getTitleText()}
|
aria-label={this.getTitleText()}
|
||||||
onClick={(e) => this.toggleOpen(e)}
|
onClick={(e) => this.toggleOpen(e)}
|
||||||
onMouseEnter={() => this.openTooltip()}
|
onMouseEnter={() => this.openTooltip()}
|
||||||
onMouseLeave={() => this.closeTooltip()}>
|
onMouseLeave={() => this.closeTooltip()}
|
||||||
|
ref={this.mainRef}>
|
||||||
|
|
||||||
<span className="sponsorBlockCategoryPillTitleSection">
|
<span className="sponsorBlockCategoryPillTitleSection">
|
||||||
<img className="sponsorSkipLogo sponsorSkipObject"
|
<img className="sponsorSkipLogo sponsorSkipObject"
|
||||||
|
|||||||
@@ -272,48 +272,49 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
</div>
|
</div>
|
||||||
): ""}
|
): ""}
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
{/* Editing Tools */}
|
{/* Editing Tools */}
|
||||||
|
|
||||||
<span id={"sponsorTimeDeleteButton" + this.idSuffix}
|
<div style={{ marginTop: "3px" }}>
|
||||||
className="sponsorTimeEditButton"
|
<span id={"sponsorTimeDeleteButton" + this.idSuffix}
|
||||||
onClick={this.deleteTime.bind(this)}>
|
|
||||||
{chrome.i18n.getMessage("delete")}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
|
|
||||||
&& this.state.selectedActionType !== ActionType.Chapter ? (
|
|
||||||
<span id={"sponsorTimePreviewButton" + this.idSuffix}
|
|
||||||
className="sponsorTimeEditButton"
|
className="sponsorTimeEditButton"
|
||||||
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
|
onClick={this.deleteTime.bind(this)}>
|
||||||
{chrome.i18n.getMessage("preview")}
|
{chrome.i18n.getMessage("delete")}
|
||||||
</span>
|
</span>
|
||||||
): ""}
|
|
||||||
|
|
||||||
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
|
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
|
||||||
<span id={"sponsorTimeInspectButton" + this.idSuffix}
|
&& this.state.selectedActionType !== ActionType.Chapter ? (
|
||||||
className="sponsorTimeEditButton"
|
<span id={"sponsorTimePreviewButton" + this.idSuffix}
|
||||||
onClick={this.inspectTime.bind(this)}>
|
className="sponsorTimeEditButton"
|
||||||
{chrome.i18n.getMessage("inspect")}
|
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
|
||||||
</span>
|
{chrome.i18n.getMessage("preview")}
|
||||||
): ""}
|
</span>
|
||||||
|
): ""}
|
||||||
|
|
||||||
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? (
|
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
|
||||||
<span id={"sponsorTimePreviewEndButton" + this.idSuffix}
|
<span id={"sponsorTimeInspectButton" + this.idSuffix}
|
||||||
className="sponsorTimeEditButton"
|
className="sponsorTimeEditButton"
|
||||||
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
|
onClick={this.inspectTime.bind(this)}>
|
||||||
{chrome.i18n.getMessage("End")}
|
{chrome.i18n.getMessage("inspect")}
|
||||||
</span>
|
</span>
|
||||||
): ""}
|
): ""}
|
||||||
|
|
||||||
|
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? (
|
||||||
|
<span id={"sponsorTimePreviewEndButton" + this.idSuffix}
|
||||||
|
className="sponsorTimeEditButton"
|
||||||
|
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
|
||||||
|
{chrome.i18n.getMessage("End")}
|
||||||
|
</span>
|
||||||
|
): ""}
|
||||||
|
|
||||||
|
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
|
||||||
|
<span id={"sponsorTimeEditButton" + this.idSuffix}
|
||||||
|
className="sponsorTimeEditButton"
|
||||||
|
onClick={this.toggleEditTime.bind(this)}>
|
||||||
|
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
|
||||||
|
</span>
|
||||||
|
): ""}
|
||||||
|
</div>
|
||||||
|
|
||||||
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
|
|
||||||
<span id={"sponsorTimeEditButton" + this.idSuffix}
|
|
||||||
className="sponsorTimeEditButton"
|
|
||||||
onClick={this.toggleEditTime.bind(this)}>
|
|
||||||
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
|
|
||||||
</span>
|
|
||||||
): ""}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ interface SBConfig {
|
|||||||
trackViewCount: boolean;
|
trackViewCount: boolean;
|
||||||
trackViewCountInPrivate: boolean;
|
trackViewCountInPrivate: boolean;
|
||||||
trackDownvotes: boolean;
|
trackDownvotes: boolean;
|
||||||
|
trackDownvotesInPrivate: boolean;
|
||||||
dontShowNotice: boolean;
|
dontShowNotice: boolean;
|
||||||
noticeVisibilityMode: NoticeVisbilityMode;
|
noticeVisibilityMode: NoticeVisbilityMode;
|
||||||
hideVideoPlayerControls: boolean;
|
hideVideoPlayerControls: boolean;
|
||||||
@@ -139,7 +140,7 @@ interface SBStorage {
|
|||||||
downvotedSegments: Record<VideoID & HashedValue, VideoDownvotes>;
|
downvotedSegments: Record<VideoID & HashedValue, VideoDownvotes>;
|
||||||
navigationApiAvailable: boolean;
|
navigationApiAvailable: boolean;
|
||||||
|
|
||||||
// Used when sync storage disbaled
|
// Used when sync storage disabled
|
||||||
alreadyInstalled: boolean;
|
alreadyInstalled: boolean;
|
||||||
|
|
||||||
/* Contains unsubmitted segments that the user has created. */
|
/* Contains unsubmitted segments that the user has created. */
|
||||||
@@ -290,6 +291,7 @@ const syncDefaults = {
|
|||||||
trackViewCount: true,
|
trackViewCount: true,
|
||||||
trackViewCountInPrivate: true,
|
trackViewCountInPrivate: true,
|
||||||
trackDownvotes: true,
|
trackDownvotes: true,
|
||||||
|
trackDownvotesInPrivate: false,
|
||||||
dontShowNotice: false,
|
dontShowNotice: false,
|
||||||
noticeVisibilityMode: NoticeVisbilityMode.FadedForAutoSkip,
|
noticeVisibilityMode: NoticeVisbilityMode.FadedForAutoSkip,
|
||||||
hideVideoPlayerControls: false,
|
hideVideoPlayerControls: false,
|
||||||
|
|||||||
261
src/content.ts
261
src/content.ts
@@ -34,7 +34,7 @@ import { ChapterVote } from "./render/ChapterVote";
|
|||||||
import { openWarningDialog } from "./utils/warnings";
|
import { openWarningDialog } from "./utils/warnings";
|
||||||
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
|
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
|
||||||
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
|
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
|
||||||
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "../maze-utils/src/video";
|
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube, getLastNonInlineVideoID, triggerVideoIDChange, triggerVideoElementChange, getIsInline } from "../maze-utils/src/video";
|
||||||
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
|
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
|
||||||
import { findValidElement } from "../maze-utils/src/dom"
|
import { findValidElement } from "../maze-utils/src/dom"
|
||||||
import { getHash, HashedValue } from "../maze-utils/src/hash";
|
import { getHash, HashedValue } from "../maze-utils/src/hash";
|
||||||
@@ -49,6 +49,7 @@ import { hideDeArrowPromotion, tryShowingDeArrowPromotion } from "./dearrowPromo
|
|||||||
import { asyncRequestToServer } from "./utils/requests";
|
import { asyncRequestToServer } from "./utils/requests";
|
||||||
import { isMobileControlsOpen } from "./utils/mobileUtils";
|
import { isMobileControlsOpen } from "./utils/mobileUtils";
|
||||||
import { defaultPreviewTime } from "./utils/constants";
|
import { defaultPreviewTime } from "./utils/constants";
|
||||||
|
import { onVideoPage } from "../maze-utils/src/pageInfo";
|
||||||
|
|
||||||
cleanPage();
|
cleanPage();
|
||||||
|
|
||||||
@@ -72,6 +73,8 @@ let sponsorDataFound = false;
|
|||||||
let sponsorTimes: SponsorTime[] = [];
|
let sponsorTimes: SponsorTime[] = [];
|
||||||
let existingChaptersImported = false;
|
let existingChaptersImported = false;
|
||||||
let importingChaptersWaitingForFocus = false;
|
let importingChaptersWaitingForFocus = false;
|
||||||
|
let importingChaptersWaiting = false;
|
||||||
|
let triedImportingChapters = false;
|
||||||
// List of open skip notices
|
// List of open skip notices
|
||||||
const skipNotices: SkipNotice[] = [];
|
const skipNotices: SkipNotice[] = [];
|
||||||
let activeSkipKeybindElement: ToggleSkippable = null;
|
let activeSkipKeybindElement: ToggleSkippable = null;
|
||||||
@@ -128,9 +131,6 @@ setupVideoModule({
|
|||||||
}, () => Config);
|
}, () => Config);
|
||||||
setupThumbnailListener();
|
setupThumbnailListener();
|
||||||
|
|
||||||
//the video id of the last preview bar update
|
|
||||||
let lastPreviewBarUpdate: VideoID;
|
|
||||||
|
|
||||||
// Is the video currently being switched
|
// Is the video currently being switched
|
||||||
let switchingVideos = null;
|
let switchingVideos = null;
|
||||||
|
|
||||||
@@ -168,7 +168,6 @@ let submissionNotice: SubmissionNotice = null;
|
|||||||
|
|
||||||
let lastResponseStatus: number;
|
let lastResponseStatus: number;
|
||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
let lookupWaiting = false;
|
|
||||||
|
|
||||||
// Contains all of the functions and variables needed by the skip notice
|
// Contains all of the functions and variables needed by the skip notice
|
||||||
const skipNoticeContentContainer: ContentContainer = () => ({
|
const skipNoticeContentContainer: ContentContainer = () => ({
|
||||||
@@ -219,7 +218,7 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
|||||||
found: sponsorDataFound,
|
found: sponsorDataFound,
|
||||||
status: lastResponseStatus,
|
status: lastResponseStatus,
|
||||||
sponsorTimes: sponsorTimes,
|
sponsorTimes: sponsorTimes,
|
||||||
time: getVideo().currentTime,
|
time: getVideo()?.currentTime ?? 0,
|
||||||
onMobileYouTube: isOnMobileYouTube()
|
onMobileYouTube: isOnMobileYouTube()
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -258,7 +257,12 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
|||||||
break;
|
break;
|
||||||
case "refreshSegments":
|
case "refreshSegments":
|
||||||
// update video on refresh if videoID invalid
|
// update video on refresh if videoID invalid
|
||||||
if (!getVideoID()) checkVideoIDChange();
|
if (!getVideoID()) {
|
||||||
|
checkVideoIDChange();
|
||||||
|
}
|
||||||
|
// if popup rescieves no response, or the videoID is invalid,
|
||||||
|
// it will assume the page is not a video page and stop the refresh animation
|
||||||
|
sendResponse({ hasVideo: getVideoID() != null });
|
||||||
// fetch segments
|
// fetch segments
|
||||||
sponsorsLookup(false);
|
sponsorsLookup(false);
|
||||||
|
|
||||||
@@ -298,7 +302,9 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
|||||||
if (!sponsorTimesSubmitting.some(
|
if (!sponsorTimesSubmitting.some(
|
||||||
(s) => Math.abs(s.segment[0] - segment.segment[0]) < 1
|
(s) => Math.abs(s.segment[0] - segment.segment[0]) < 1
|
||||||
&& Math.abs(s.segment[1] - segment.segment[1]) < 1)) {
|
&& Math.abs(s.segment[1] - segment.segment[1]) < 1)) {
|
||||||
if (segment.category === "chapter" && !utils.getCategorySelection("chapter")) {
|
const hasChaptersPermission = (Config.config.showCategoryWithoutPermission
|
||||||
|
|| Config.config.permissions["chapter"]);
|
||||||
|
if (segment.category === "chapter" && (!utils.getCategorySelection("chapter") || !hasChaptersPermission)) {
|
||||||
segment.category = "chooseACategory" as Category;
|
segment.category = "chooseACategory" as Category;
|
||||||
segment.actionType = ActionType.Skip;
|
segment.actionType = ActionType.Skip;
|
||||||
segment.description = "";
|
segment.description = "";
|
||||||
@@ -377,6 +383,7 @@ function resetValues() {
|
|||||||
|
|
||||||
sponsorTimes = [];
|
sponsorTimes = [];
|
||||||
existingChaptersImported = false;
|
existingChaptersImported = false;
|
||||||
|
triedImportingChapters = false;
|
||||||
sponsorSkipped = [];
|
sponsorSkipped = [];
|
||||||
lastResponseStatus = 0;
|
lastResponseStatus = 0;
|
||||||
shownSegmentFailedToFetchWarning = false;
|
shownSegmentFailedToFetchWarning = false;
|
||||||
@@ -393,8 +400,9 @@ function resetValues() {
|
|||||||
//reset sponsor data found check
|
//reset sponsor data found check
|
||||||
sponsorDataFound = false;
|
sponsorDataFound = false;
|
||||||
|
|
||||||
if (switchingVideos === null) {
|
// When first loading a video, it is not switching videos
|
||||||
// When first loading a video, it is not switching videos
|
// Hover play also doesn't need this check
|
||||||
|
if (switchingVideos === null || !onVideoPage()) {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
} else {
|
} else {
|
||||||
switchingVideos = true;
|
switchingVideos = true;
|
||||||
@@ -451,6 +459,17 @@ function videoIDChange(): void {
|
|||||||
updateSponsorTimesSubmitting();
|
updateSponsorTimesSubmitting();
|
||||||
|
|
||||||
tryShowingDeArrowPromotion().catch(logWarn);
|
tryShowingDeArrowPromotion().catch(logWarn);
|
||||||
|
|
||||||
|
checkPreviewbarState();
|
||||||
|
|
||||||
|
if (getIsInline()) {
|
||||||
|
// Hover preview progress bar can take some time to appear
|
||||||
|
// and if the miniplayer is also active then it would
|
||||||
|
// attach to the wrong one
|
||||||
|
setTimeout(checkPreviewbarState, 500);
|
||||||
|
setTimeout(checkPreviewbarState, 1000);
|
||||||
|
setTimeout(checkPreviewbarState, 3000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMobileControlsMutations(): void {
|
function handleMobileControlsMutations(): void {
|
||||||
@@ -479,12 +498,7 @@ function handleMobileControlsMutations(): void {
|
|||||||
createPreviewBar();
|
createPreviewBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function getPreviewBarAttachElement(): HTMLElement | null {
|
||||||
* Creates a preview bar on the video
|
|
||||||
*/
|
|
||||||
function createPreviewBar(): void {
|
|
||||||
if (previewBar !== null) return;
|
|
||||||
|
|
||||||
const progressElementOptions = [{
|
const progressElementOptions = [{
|
||||||
// For new mobile YouTube (#1287)
|
// For new mobile YouTube (#1287)
|
||||||
selector: ".progress-bar-line",
|
selector: ".progress-bar-line",
|
||||||
@@ -494,11 +508,22 @@ function createPreviewBar(): void {
|
|||||||
selector: ".YtProgressBarProgressBarLine",
|
selector: ".YtProgressBarProgressBarLine",
|
||||||
isVisibleCheck: true
|
isVisibleCheck: true
|
||||||
}, {
|
}, {
|
||||||
// For Desktop YouTube
|
// For newer mobile YouTube (May 2024)
|
||||||
|
selector: ".YtmProgressBarProgressBarLine",
|
||||||
|
isVisibleCheck: true
|
||||||
|
}, {
|
||||||
|
// For desktop YouTube hover play
|
||||||
|
// Priority is given to the hover play progress bar over the main progress bar
|
||||||
|
// for miniplayer + hover preview case
|
||||||
|
// Second is new hover play selector
|
||||||
|
selector: "#video-preview .ytp-progress-bar, #video-preview .YtProgressBarLineHost",
|
||||||
|
isVisibleCheck: true
|
||||||
|
}, {
|
||||||
|
// For desktop YouTube
|
||||||
selector: ".ytp-progress-bar",
|
selector: ".ytp-progress-bar",
|
||||||
isVisibleCheck: true
|
isVisibleCheck: true
|
||||||
}, {
|
}, {
|
||||||
// For Desktop YouTube
|
// For desktop YouTube
|
||||||
selector: ".no-model.cue-range-marker",
|
selector: ".no-model.cue-range-marker",
|
||||||
isVisibleCheck: true
|
isVisibleCheck: true
|
||||||
}, {
|
}, {
|
||||||
@@ -521,14 +546,27 @@ function createPreviewBar(): void {
|
|||||||
const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0];
|
const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0];
|
||||||
|
|
||||||
if (el) {
|
if (el) {
|
||||||
const chapterVote = new ChapterVote(voteAsync);
|
return el;
|
||||||
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
|
|
||||||
|
|
||||||
updatePreviewBar();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a preview bar on the video
|
||||||
|
*/
|
||||||
|
function createPreviewBar(): void {
|
||||||
|
if (previewBar !== null) return;
|
||||||
|
|
||||||
|
const el = getPreviewBarAttachElement();
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
const chapterVote = new ChapterVote(voteAsync);
|
||||||
|
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
|
||||||
|
|
||||||
|
updatePreviewBar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -782,6 +820,8 @@ function inMuteSegment(currentTime: number, includeOverlap: boolean): boolean {
|
|||||||
* This makes sure the videoID is still correct and if the sponsorTime is included
|
* This makes sure the videoID is still correct and if the sponsorTime is included
|
||||||
*/
|
*/
|
||||||
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
|
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
|
||||||
|
if (!onVideoPage()) return false;
|
||||||
|
|
||||||
const currentVideoID = getYouTubeVideoID();
|
const currentVideoID = getYouTubeVideoID();
|
||||||
const recordedVideoID = videoID || getVideoID();
|
const recordedVideoID = videoID || getVideoID();
|
||||||
if (currentVideoID !== recordedVideoID || (sponsorTime
|
if (currentVideoID !== recordedVideoID || (sponsorTime
|
||||||
@@ -805,14 +845,16 @@ let playbackRateCheckInterval: NodeJS.Timeout | null = null;
|
|||||||
let lastPlaybackSpeed = 1;
|
let lastPlaybackSpeed = 1;
|
||||||
let setupVideoListenersFirstTime = true;
|
let setupVideoListenersFirstTime = true;
|
||||||
function setupVideoListeners() {
|
function setupVideoListeners() {
|
||||||
|
const video = getVideo();
|
||||||
|
|
||||||
//wait until it is loaded
|
//wait until it is loaded
|
||||||
getVideo().addEventListener('loadstart', videoOnReadyListener)
|
video.addEventListener('loadstart', videoOnReadyListener)
|
||||||
getVideo().addEventListener('durationchange', durationChangeListener);
|
video.addEventListener('durationchange', durationChangeListener);
|
||||||
|
|
||||||
if (setupVideoListenersFirstTime) {
|
if (setupVideoListenersFirstTime) {
|
||||||
addCleanupListener(() => {
|
addCleanupListener(() => {
|
||||||
getVideo().removeEventListener('loadstart', videoOnReadyListener);
|
video.removeEventListener('loadstart', videoOnReadyListener);
|
||||||
getVideo().removeEventListener('durationchange', durationChangeListener);
|
video.removeEventListener('durationchange', durationChangeListener);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,18 +870,20 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('ratechange', rateChangeListener);
|
video.addEventListener('ratechange', rateChangeListener);
|
||||||
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
|
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
|
||||||
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
|
video.addEventListener('videoSpeed_ratechange', rateChangeListener);
|
||||||
|
|
||||||
const playListener = () => {
|
const playListener = () => {
|
||||||
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
||||||
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
||||||
// gone back to the begining
|
// gone back to the begining
|
||||||
if (getVideo().readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
|
if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
|
||||||
&& getVideo().currentTime === 0) return;
|
&& video.currentTime === 0) return;
|
||||||
|
|
||||||
|
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
|
checkForMiniplayerPlaying();
|
||||||
|
|
||||||
if (switchingVideos || lastPausedAtZero) {
|
if (switchingVideos || lastPausedAtZero) {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
@@ -855,15 +899,15 @@ function setupVideoListeners() {
|
|||||||
updateAdFlag();
|
updateAdFlag();
|
||||||
|
|
||||||
// Make sure it doesn't get double called with the playing event
|
// Make sure it doesn't get double called with the playing event
|
||||||
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
||||||
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) {
|
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
|
||||||
lastCheckTime = Date.now();
|
lastCheckTime = Date.now();
|
||||||
lastCheckVideoTime = getVideo().currentTime;
|
lastCheckVideoTime = video.currentTime;
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('play', playListener);
|
video.addEventListener('play', playListener);
|
||||||
|
|
||||||
const playingListener = () => {
|
const playingListener = () => {
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
@@ -871,8 +915,8 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
if (startedWaiting) {
|
if (startedWaiting) {
|
||||||
startedWaiting = false;
|
startedWaiting = false;
|
||||||
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
||||||
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)}`);
|
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchingVideos) {
|
if (switchingVideos) {
|
||||||
@@ -884,63 +928,63 @@ function setupVideoListeners() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it doesn't get double called with the play event
|
// Make sure it doesn't get double called with the play event
|
||||||
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3
|
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
||||||
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) {
|
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
|
||||||
lastCheckTime = Date.now();
|
lastCheckTime = Date.now();
|
||||||
lastCheckVideoTime = getVideo().currentTime;
|
lastCheckVideoTime = video.currentTime;
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
|
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
|
||||||
lastPlaybackSpeed = getVideo().playbackRate;
|
lastPlaybackSpeed = video.playbackRate;
|
||||||
|
|
||||||
// Video speed controller compatibility
|
// Video speed controller compatibility
|
||||||
// That extension makes rate change events not propagate
|
// That extension makes rate change events not propagate
|
||||||
if (document.body.classList.contains("vsc-initialized")) {
|
if (document.body.classList.contains("vsc-initialized")) {
|
||||||
playbackRateCheckInterval = setInterval(() => {
|
playbackRateCheckInterval = setInterval(() => {
|
||||||
if ((!getVideoID() || getVideo().paused) && playbackRateCheckInterval) {
|
if ((!getVideoID() || video.paused) && playbackRateCheckInterval) {
|
||||||
// Video is gone, stop checking
|
// Video is gone, stop checking
|
||||||
clearInterval(playbackRateCheckInterval);
|
clearInterval(playbackRateCheckInterval);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getVideo().playbackRate !== lastPlaybackSpeed) {
|
if (video.playbackRate !== lastPlaybackSpeed) {
|
||||||
lastPlaybackSpeed = getVideo().playbackRate;
|
lastPlaybackSpeed = video.playbackRate;
|
||||||
|
|
||||||
rateChangeListener();
|
rateChangeListener();
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('playing', playingListener);
|
video.addEventListener('playing', playingListener);
|
||||||
|
|
||||||
const seekingListener = () => {
|
const seekingListener = () => {
|
||||||
lastKnownVideoTime.fromPause = false;
|
lastKnownVideoTime.fromPause = false;
|
||||||
|
|
||||||
if (!getVideo().paused){
|
if (!video.paused){
|
||||||
// Reset lastCheckVideoTime
|
// Reset lastCheckVideoTime
|
||||||
lastCheckTime = Date.now();
|
lastCheckTime = Date.now();
|
||||||
lastCheckVideoTime = getVideo().currentTime;
|
lastCheckVideoTime = video.currentTime;
|
||||||
|
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
clearWaitingTime();
|
clearWaitingTime();
|
||||||
|
|
||||||
// Sometimes looped videos loop back to almost zero, but not quite
|
// Sometimes looped videos loop back to almost zero, but not quite
|
||||||
if (getVideo().loop && getVideo().currentTime < 0.2) {
|
if (video.loop && video.currentTime < 0.2) {
|
||||||
startSponsorSchedule(false, 0);
|
startSponsorSchedule(false, 0);
|
||||||
} else {
|
} else {
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updateActiveSegment(getVideo().currentTime);
|
updateActiveSegment(video.currentTime);
|
||||||
|
|
||||||
if (getVideo().currentTime === 0) {
|
if (video.currentTime === 0) {
|
||||||
lastPausedAtZero = true;
|
lastPausedAtZero = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('seeking', seekingListener);
|
video.addEventListener('seeking', seekingListener);
|
||||||
|
|
||||||
const stoppedPlayback = () => {
|
const stoppedPlayback = () => {
|
||||||
// Reset lastCheckVideoTime
|
// Reset lastCheckVideoTime
|
||||||
@@ -951,7 +995,7 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
lastKnownVideoTime.videoTime = null;
|
lastKnownVideoTime.videoTime = null;
|
||||||
lastKnownVideoTime.preciseTime = null;
|
lastKnownVideoTime.preciseTime = null;
|
||||||
updateWaitingTime();
|
updateWaitingTime(video);
|
||||||
|
|
||||||
cancelSponsorSchedule();
|
cancelSponsorSchedule();
|
||||||
};
|
};
|
||||||
@@ -960,26 +1004,26 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
stoppedPlayback();
|
stoppedPlayback();
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('pause', pauseListener);
|
video.addEventListener('pause', pauseListener);
|
||||||
const waitingListener = () => {
|
const waitingListener = () => {
|
||||||
logDebug("[SB] Not skipping due to buffering");
|
logDebug("[SB] Not skipping due to buffering");
|
||||||
startedWaiting = true;
|
startedWaiting = true;
|
||||||
|
|
||||||
stoppedPlayback();
|
stoppedPlayback();
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('waiting', waitingListener);
|
video.addEventListener('waiting', waitingListener);
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
|
|
||||||
if (setupVideoListenersFirstTime) {
|
if (setupVideoListenersFirstTime) {
|
||||||
addCleanupListener(() => {
|
addCleanupListener(() => {
|
||||||
getVideo().removeEventListener('play', playListener);
|
video.removeEventListener('play', playListener);
|
||||||
getVideo().removeEventListener('playing', playingListener);
|
video.removeEventListener('playing', playingListener);
|
||||||
getVideo().removeEventListener('seeking', seekingListener);
|
video.removeEventListener('seeking', seekingListener);
|
||||||
getVideo().removeEventListener('ratechange', rateChangeListener);
|
video.removeEventListener('ratechange', rateChangeListener);
|
||||||
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener);
|
video.removeEventListener('videoSpeed_ratechange', rateChangeListener);
|
||||||
getVideo().removeEventListener('pause', pauseListener);
|
video.removeEventListener('pause', pauseListener);
|
||||||
getVideo().removeEventListener('waiting', waitingListener);
|
video.removeEventListener('waiting', waitingListener);
|
||||||
|
|
||||||
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
|
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
|
||||||
});
|
});
|
||||||
@@ -1030,8 +1074,8 @@ function updateVirtualTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWaitingTime(): void {
|
function updateWaitingTime(video: HTMLVideoElement): void {
|
||||||
lastTimeFromWaitingEvent = getVideo().currentTime;
|
lastTimeFromWaitingEvent = video.currentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearWaitingTime(): void {
|
function clearWaitingTime(): void {
|
||||||
@@ -1065,17 +1109,6 @@ function setupCategoryPill() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function sponsorsLookup(keepOldSubmissions = true) {
|
async function sponsorsLookup(keepOldSubmissions = true) {
|
||||||
if (lookupWaiting) return;
|
|
||||||
//there is still no video here
|
|
||||||
if (!getVideo()) {
|
|
||||||
lookupWaiting = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
lookupWaiting = false;
|
|
||||||
sponsorsLookup()
|
|
||||||
}, 100);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const categories: string[] = Config.config.categorySelections.map((category) => category.name);
|
const categories: string[] = Config.config.categorySelections.map((category) => category.name);
|
||||||
|
|
||||||
const extraRequestData: Record<string, unknown> = {};
|
const extraRequestData: Record<string, unknown> = {};
|
||||||
@@ -1152,13 +1185,14 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!getVideo()) {
|
||||||
|
//there is still no video here
|
||||||
|
await waitFor(() => getVideo(), 5000, 10);
|
||||||
|
}
|
||||||
|
|
||||||
startSkipScheduleCheckingForStartSponsors();
|
startSkipScheduleCheckingForStartSponsors();
|
||||||
|
|
||||||
//update the preview bar
|
if (!isNaN(getVideo().duration)) {
|
||||||
//leave the type blank for now until categories are added
|
|
||||||
if (lastPreviewBarUpdate == getVideoID() || (lastPreviewBarUpdate == null && !isNaN(getVideo().duration))) {
|
|
||||||
//set it now
|
|
||||||
//otherwise the listener can handle it
|
|
||||||
updatePreviewBar();
|
updatePreviewBar();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1176,7 +1210,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
|||||||
found: sponsorDataFound,
|
found: sponsorDataFound,
|
||||||
status: lastResponseStatus,
|
status: lastResponseStatus,
|
||||||
sponsorTimes: sponsorTimes,
|
sponsorTimes: sponsorTimes,
|
||||||
time: getVideo().currentTime,
|
time: getVideo()?.currentTime ?? 0,
|
||||||
onMobileYouTube: isOnMobileYouTube()
|
onMobileYouTube: isOnMobileYouTube()
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1186,10 +1220,10 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function importExistingChapters(wait: boolean) {
|
function importExistingChapters(wait: boolean) {
|
||||||
if (!existingChaptersImported) {
|
if (!existingChaptersImported && !importingChaptersWaiting && !triedImportingChapters && onVideoPage() && !isOnMobileYouTube()) {
|
||||||
const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration);
|
const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration);
|
||||||
|
|
||||||
if (!waitCondition() && wait && !document.hasFocus() && !importingChaptersWaitingForFocus) {
|
if (wait && !document.hasFocus() && !importingChaptersWaitingForFocus && !waitCondition()) {
|
||||||
importingChaptersWaitingForFocus = true;
|
importingChaptersWaitingForFocus = true;
|
||||||
const listener = () => {
|
const listener = () => {
|
||||||
importExistingChapters(wait);
|
importExistingChapters(wait);
|
||||||
@@ -1197,14 +1231,17 @@ function importExistingChapters(wait: boolean) {
|
|||||||
};
|
};
|
||||||
window.addEventListener("focus", listener);
|
window.addEventListener("focus", listener);
|
||||||
} else {
|
} else {
|
||||||
|
importingChaptersWaiting = true;
|
||||||
waitFor(waitCondition,
|
waitFor(waitCondition,
|
||||||
wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => {
|
wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => {
|
||||||
|
importingChaptersWaiting = false;
|
||||||
|
|
||||||
if (!existingChaptersImported && chapters?.length > 0) {
|
if (!existingChaptersImported && chapters?.length > 0) {
|
||||||
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
|
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
|
||||||
existingChaptersImported = true;
|
existingChaptersImported = true;
|
||||||
updatePreviewBar();
|
updatePreviewBar();
|
||||||
}
|
}
|
||||||
}).catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
|
}).catch(() => { importingChaptersWaiting = false; triedImportingChapters = true; }); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1376,9 +1413,6 @@ function updatePreviewBar(): void {
|
|||||||
|
|
||||||
showTimeWithoutSkips(skippedDuration);
|
showTimeWithoutSkips(skippedDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last video id
|
|
||||||
lastPreviewBarUpdate = getVideoID();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//checks if this channel is whitelisted, should be done only after the channelID has been loaded
|
//checks if this channel is whitelisted, should be done only after the channelID has been loaded
|
||||||
@@ -1402,7 +1436,8 @@ function videoElementChange(newVideo: boolean): void {
|
|||||||
setupSkipButtonControlBar();
|
setupSkipButtonControlBar();
|
||||||
setupCategoryPill();
|
setupCategoryPill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePreviewBar();
|
||||||
checkPreviewbarState();
|
checkPreviewbarState();
|
||||||
|
|
||||||
// Incase the page is still transitioning, check again in a few seconds
|
// Incase the page is still transitioning, check again in a few seconds
|
||||||
@@ -1412,8 +1447,19 @@ function videoElementChange(newVideo: boolean): void {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let checkingPreviewbarAgain = false;
|
||||||
function checkPreviewbarState(): void {
|
function checkPreviewbarState(): void {
|
||||||
if (previewBar && !utils.findReferenceNode()?.contains(previewBar.container)) {
|
if (!getPreviewBarAttachElement() && !checkingPreviewbarAgain && getVideo() && getVideoID()) {
|
||||||
|
checkingPreviewbarAgain = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
checkingPreviewbarAgain = false;
|
||||||
|
checkPreviewbarState();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previewBar && !getPreviewBarAttachElement()?.contains(previewBar.container)) {
|
||||||
previewBar.remove();
|
previewBar.remove();
|
||||||
previewBar = null;
|
previewBar = null;
|
||||||
}
|
}
|
||||||
@@ -1595,6 +1641,13 @@ function previewTime(time: number, unpause = true) {
|
|||||||
|
|
||||||
//send telemetry and count skip
|
//send telemetry and count skip
|
||||||
function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: number, fullSkip: boolean) {
|
function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: number, fullSkip: boolean) {
|
||||||
|
for (const segment of skippingSegments) {
|
||||||
|
if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
|
||||||
|
// Count that as a previewed segment
|
||||||
|
previewedSegment = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Config.config.trackViewCount || (!Config.config.trackViewCountInPrivate && chrome.extension.inIncognitoContext)) return;
|
if (!Config.config.trackViewCount || (!Config.config.trackViewCountInPrivate && chrome.extension.inIncognitoContext)) return;
|
||||||
|
|
||||||
let counted = false;
|
let counted = false;
|
||||||
@@ -1611,9 +1664,6 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
|
if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
|
||||||
} else if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
|
|
||||||
// Count that as a previewed segment
|
|
||||||
previewedSegment = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1624,8 +1674,9 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
|
|||||||
|
|
||||||
// There will only be one submission if it is manual skip
|
// There will only be one submission if it is manual skip
|
||||||
const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]);
|
const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]);
|
||||||
|
const isSubmittingSegment = sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment);
|
||||||
|
|
||||||
if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment))
|
if ((autoSkip || isSubmittingSegment)
|
||||||
&& v.currentTime !== skipTime[1]) {
|
&& v.currentTime !== skipTime[1]) {
|
||||||
switch(skippingSegments[0].actionType) {
|
switch(skippingSegments[0].actionType) {
|
||||||
case ActionType.Poi:
|
case ActionType.Poi:
|
||||||
@@ -1706,7 +1757,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send telemetry that a this sponsor was skipped
|
//send telemetry that a this sponsor was skipped
|
||||||
if (autoSkip) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true);
|
if (autoSkip || isSubmittingSegment) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSkipNotice(skippingSegments: SponsorTime[], autoSkip: boolean, unskipTime: number, startReskip: boolean) {
|
function createSkipNotice(skippingSegments: SponsorTime[], autoSkip: boolean, unskipTime: number, startReskip: boolean) {
|
||||||
@@ -1796,7 +1847,8 @@ function shouldAutoSkip(segment: SponsorTime): boolean {
|
|||||||
return (!Config.config.manualSkipOnFullVideo || !sponsorTimes?.some((s) => s.category === segment.category && s.actionType === ActionType.Full))
|
return (!Config.config.manualSkipOnFullVideo || !sponsorTimes?.some((s) => s.category === segment.category && s.actionType === ActionType.Full))
|
||||||
&& (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));
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldSkip(segment: SponsorTime): boolean {
|
function shouldSkip(segment: SponsorTime): boolean {
|
||||||
@@ -2663,3 +2715,22 @@ function setCategoryColorCSSVariables() {
|
|||||||
|
|
||||||
styleContainer.innerText = css;
|
styleContainer.innerText = css;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If mini player starts playing, then videoID change might have to be called
|
||||||
|
*/
|
||||||
|
function checkForMiniplayerPlaying() {
|
||||||
|
const miniPlayerUI = document.querySelector(".miniplayer") as HTMLElement;
|
||||||
|
if (!onVideoPage() && isVisible(miniPlayerUI)) {
|
||||||
|
const videoID = getLastNonInlineVideoID();
|
||||||
|
if (videoID) {
|
||||||
|
triggerVideoIDChange(videoID);
|
||||||
|
|
||||||
|
// treat as if video element has changed
|
||||||
|
const video = miniPlayerUI.querySelector("video") as HTMLVideoElement;
|
||||||
|
if (video && getVideo() !== video) {
|
||||||
|
triggerVideoElementChange(video);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
|
|||||||
import { normalizeChapterName } from "../utils/exporter";
|
import { normalizeChapterName } from "../utils/exporter";
|
||||||
import { findValidElement } from "../../maze-utils/src/dom";
|
import { findValidElement } from "../../maze-utils/src/dom";
|
||||||
import { addCleanupListener } from "../../maze-utils/src/cleanup";
|
import { addCleanupListener } from "../../maze-utils/src/cleanup";
|
||||||
|
import { isVisible } from "../utils/pageUtils";
|
||||||
|
|
||||||
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
||||||
const MIN_CHAPTER_SIZE = 0.003;
|
const MIN_CHAPTER_SIZE = 0.003;
|
||||||
@@ -225,10 +226,12 @@ class PreviewBar {
|
|||||||
this.segments = segments ?? [];
|
this.segments = segments ?? [];
|
||||||
this.videoDuration = videoDuration ?? 0;
|
this.videoDuration = videoDuration ?? 0;
|
||||||
|
|
||||||
|
|
||||||
this.updatePageElements();
|
this.updatePageElements();
|
||||||
// Sometimes video duration is inaccurate, pull from accessibility info
|
// Sometimes video duration is inaccurate, pull from accessibility info
|
||||||
const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0;
|
const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0;
|
||||||
if (ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
|
const multipleActiveVideos = [...document.querySelectorAll("video")].filter((v) => isVisible(v)).length > 1;
|
||||||
|
if (!multipleActiveVideos && ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
|
||||||
this.videoDuration = ariaDuration;
|
this.videoDuration = ariaDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +239,7 @@ class PreviewBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updatePageElements(): void {
|
private updatePageElements(): void {
|
||||||
const allProgressBars = document.querySelectorAll('.ytp-progress-bar') as NodeListOf<HTMLElement>;
|
const allProgressBars = document.querySelectorAll(".ytp-progress-bar") as NodeListOf<HTMLElement>;
|
||||||
this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0];
|
this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0];
|
||||||
|
|
||||||
if (this.progressBar) {
|
if (this.progressBar) {
|
||||||
@@ -748,6 +751,7 @@ class PreviewBar {
|
|||||||
|
|
||||||
updateChapterText(segments: SponsorTime[], submittingSegments: SponsorTime[], currentTime: number): SponsorTime[] {
|
updateChapterText(segments: SponsorTime[], submittingSegments: SponsorTime[], currentTime: number): SponsorTime[] {
|
||||||
if (!Config.config.showSegmentNameInChapterBar
|
if (!Config.config.showSegmentNameInChapterBar
|
||||||
|
|| Config.config.disableSkipping
|
||||||
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
|
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
|
||||||
const chaptersContainer = this.getChaptersContainer();
|
const chaptersContainer = this.getChaptersContainer();
|
||||||
if (chaptersContainer) {
|
if (chaptersContainer) {
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ export type MessageResponse =
|
|||||||
| IsChannelWhitelistedResponse
|
| IsChannelWhitelistedResponse
|
||||||
| Record<string, never> // empty object response {}
|
| Record<string, never> // empty object response {}
|
||||||
| VoteResponse
|
| VoteResponse
|
||||||
| ImportSegmentsResponse;
|
| ImportSegmentsResponse
|
||||||
|
| RefreshSegmentsResponse;
|
||||||
|
|
||||||
export interface VoteResponse {
|
export interface VoteResponse {
|
||||||
successType: number;
|
successType: number;
|
||||||
@@ -115,6 +116,10 @@ interface ImportSegmentsResponse {
|
|||||||
importedSegments: SponsorTime[];
|
importedSegments: SponsorTime[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RefreshSegmentsResponse {
|
||||||
|
hasVideo: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TimeUpdateMessage {
|
export interface TimeUpdateMessage {
|
||||||
message: "time";
|
message: "time";
|
||||||
time: number;
|
time: number;
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ async function init() {
|
|||||||
break;
|
break;
|
||||||
case "resetToDefault":
|
case "resetToDefault":
|
||||||
Config.resetToDefault();
|
Config.resetToDefault();
|
||||||
window.location.reload();
|
setTimeout(() => window.location.reload(), 200);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -632,8 +632,7 @@ async function setTextOption(option: string, element: HTMLElement, value: string
|
|||||||
await invidiousOnClick(checkbox, "supportInvidious");
|
await invidiousOnClick(checkbox, "supportInvidious");
|
||||||
}
|
}
|
||||||
|
|
||||||
window.location.reload();
|
setTimeout(() => window.location.reload(), 200);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(chrome.i18n.getMessage("incorrectlyFormattedOptions"));
|
alert(chrome.i18n.getMessage("incorrectlyFormattedOptions"));
|
||||||
}
|
}
|
||||||
|
|||||||
59
src/popup.ts
59
src/popup.ts
@@ -15,6 +15,7 @@ import {
|
|||||||
Message,
|
Message,
|
||||||
MessageResponse,
|
MessageResponse,
|
||||||
PopupMessage,
|
PopupMessage,
|
||||||
|
RefreshSegmentsResponse,
|
||||||
SponsorStartResponse,
|
SponsorStartResponse,
|
||||||
VoteResponse,
|
VoteResponse,
|
||||||
} from "./messageTypes";
|
} from "./messageTypes";
|
||||||
@@ -459,37 +460,35 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
stopLoadingAnimation = null;
|
stopLoadingAnimation = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError || request == undefined || request.found == undefined) {
|
||||||
//This page doesn't have the injected content script, or at least not yet
|
//This page doesn't have the injected content script, or at least not yet
|
||||||
|
// Or if the request is empty, meaning the current page is not YouTube or a video page
|
||||||
displayNoVideo();
|
displayNoVideo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if request is undefined, then the page currently being browsed is not YouTube
|
//remove loading text
|
||||||
if (request != undefined) {
|
PageElements.mainControls.style.display = "block";
|
||||||
//remove loading text
|
if (request.onMobileYouTube) PageElements.mainControls.classList.add("hidden");
|
||||||
PageElements.mainControls.style.display = "block";
|
PageElements.whitelistButton.classList.remove("hidden");
|
||||||
if (request.onMobileYouTube) PageElements.mainControls.classList.add("hidden");
|
PageElements.loadingIndicator.style.display = "none";
|
||||||
PageElements.whitelistButton.classList.remove("hidden");
|
|
||||||
PageElements.loadingIndicator.style.display = "none";
|
|
||||||
|
|
||||||
downloadedTimes = request.sponsorTimes ?? [];
|
downloadedTimes = request.sponsorTimes ?? [];
|
||||||
displayDownloadedSponsorTimes(downloadedTimes, request.time);
|
displayDownloadedSponsorTimes(downloadedTimes, request.time);
|
||||||
if (request.found) {
|
if (request.found) {
|
||||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound");
|
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound");
|
||||||
PageElements.issueReporterImportExport.classList.remove("hidden");
|
PageElements.issueReporterImportExport.classList.remove("hidden");
|
||||||
} else if (request.status == 404 || request.status == 200) {
|
} else if (request.status == 404 || request.status == 200) {
|
||||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404");
|
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404");
|
||||||
PageElements.issueReporterImportExport.classList.remove("hidden");
|
PageElements.issueReporterImportExport.classList.remove("hidden");
|
||||||
|
} else {
|
||||||
|
if (request.status) {
|
||||||
|
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("connectionError") + request.status;
|
||||||
} else {
|
} else {
|
||||||
if (request.status) {
|
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("segmentsStillLoading");
|
||||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("connectionError") + request.status;
|
|
||||||
} else {
|
|
||||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("segmentsStillLoading");
|
|
||||||
}
|
|
||||||
|
|
||||||
PageElements.issueReporterImportExport.classList.remove("hidden");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageElements.issueReporterImportExport.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
//see if whitelist button should be swapped
|
//see if whitelist button should be swapped
|
||||||
@@ -562,7 +561,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.segment[1] - b.segment[1])
|
.sort((a, b) => b.segment[1] - a.segment[1])
|
||||||
.sort((a, b) => a.segment[0] - b.segment[0]);
|
.sort((a, b) => a.segment[0] - b.segment[0]);
|
||||||
|
|
||||||
//add them as buttons to the issue reporting container
|
//add them as buttons to the issue reporting container
|
||||||
@@ -980,9 +979,17 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
|||||||
stopLoadingAnimation = AnimationUtils.applyLoadingAnimation(PageElements.refreshSegmentsButton, 0.3);
|
stopLoadingAnimation = AnimationUtils.applyLoadingAnimation(PageElements.refreshSegmentsButton, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshSegments() {
|
async function refreshSegments() {
|
||||||
startLoadingAnimation();
|
startLoadingAnimation();
|
||||||
sendTabMessage({ message: 'refreshSegments' });
|
const response = await sendTabMessageAsync({ message: 'refreshSegments' }) as RefreshSegmentsResponse;
|
||||||
|
|
||||||
|
if (response == null || !response.hasVideo) {
|
||||||
|
if (stopLoadingAnimation != null) {
|
||||||
|
stopLoadingAnimation();
|
||||||
|
stopLoadingAnimation = null;
|
||||||
|
}
|
||||||
|
displayNoVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipSegment(actionType: ActionType, UUID: SegmentUUID, element?: HTMLElement): void {
|
function skipSegment(actionType: ActionType, UUID: SegmentUUID, element?: HTMLElement): void {
|
||||||
|
|||||||
@@ -43,9 +43,15 @@ export class CategoryPill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async attachToPageInternal(): Promise<void> {
|
private async attachToPageInternal(): Promise<void> {
|
||||||
const referenceNode =
|
let referenceNode =
|
||||||
await waitFor(() => getYouTubeTitleNode());
|
await waitFor(() => getYouTubeTitleNode());
|
||||||
|
|
||||||
|
// Experimental YouTube layout with description on right
|
||||||
|
const isOnDescriptionOnRightLayout = document.querySelector("#title #description");
|
||||||
|
if (isOnDescriptionOnRightLayout) {
|
||||||
|
referenceNode = referenceNode.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
if (referenceNode && !referenceNode.contains(this.container)) {
|
if (referenceNode && !referenceNode.contains(this.container)) {
|
||||||
if (!this.container) {
|
if (!this.container) {
|
||||||
this.container = document.createElement('span');
|
this.container = document.createElement('span');
|
||||||
@@ -91,7 +97,9 @@ export class CategoryPill {
|
|||||||
parent.appendChild(this.container);
|
parent.appendChild(this.container);
|
||||||
|
|
||||||
referenceNode.prepend(parent);
|
referenceNode.prepend(parent);
|
||||||
referenceNode.style.display = "flex";
|
if (!isOnDescriptionOnRightLayout) {
|
||||||
|
referenceNode.style.display = "flex";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +281,8 @@ export default class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async addHiddenSegment(videoID: VideoID, segmentUUID: string, hidden: SponsorHideType) {
|
async addHiddenSegment(videoID: VideoID, segmentUUID: string, hidden: SponsorHideType) {
|
||||||
if (chrome.extension.inIncognitoContext || !Config.config.trackDownvotes) return;
|
if ((chrome.extension.inIncognitoContext && !Config.config.trackDownvotesInPrivate)
|
||||||
|
|| !Config.config.trackDownvotes) return;
|
||||||
|
|
||||||
const hashedVideoID = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue;
|
const hashedVideoID = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue;
|
||||||
const UUIDHash = await getHash(segmentUUID, 1);
|
const UUIDHash = await getHash(segmentUUID, 1);
|
||||||
|
|||||||
@@ -53,24 +53,23 @@ export function importTimes(data: string, videoDuration: number): SponsorTime[]
|
|||||||
titleRight = removeIf(split2[split2.length - 1], specialCharMatchers)
|
titleRight = removeIf(split2[split2.length - 1], specialCharMatchers)
|
||||||
|
|
||||||
const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight;
|
const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight;
|
||||||
if (title) {
|
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
|
||||||
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
|
|
||||||
|
|
||||||
const segment: SponsorTime = {
|
const category = title ? (determinedCategory ?? ("chapter" as Category)) : "chooseACategory" as Category;
|
||||||
segment: [startTime, getFormattedTimeToSeconds(match[1])],
|
const segment: SponsorTime = {
|
||||||
category: determinedCategory ?? ("chapter" as Category),
|
segment: [startTime, getFormattedTimeToSeconds(match[1])],
|
||||||
actionType: determinedCategory ? ActionType.Skip : ActionType.Chapter,
|
category,
|
||||||
description: title,
|
actionType: category === "chapter" ? ActionType.Chapter : ActionType.Skip,
|
||||||
source: SponsorSourceType.Local,
|
description: category === "chapter" ? title : null,
|
||||||
UUID: generateUserID() as SegmentUUID
|
source: SponsorSourceType.Local,
|
||||||
};
|
UUID: generateUserID() as SegmentUUID
|
||||||
|
};
|
||||||
|
|
||||||
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
|
if (result.length > 0 && result[result.length - 1].segment[1] === null) {
|
||||||
result[result.length - 1].segment[1] = segment.segment[0];
|
result[result.length - 1].segment[1] = segment.segment[0];
|
||||||
}
|
|
||||||
|
|
||||||
result.push(segment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.push(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user