diff options
author | Ajay Ramachandran <[email protected]> | 2021-08-20 03:57:27 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2021-08-20 03:57:27 -0400 |
commit | 032264d8bbd05e295a8f25acc3dc024c67432677 (patch) | |
tree | c1baebd3fb89790859d39996e7bf8f77d43ace94 | |
parent | 12f41521f5382bd0f8a86f58adba69cba7d11b7e (diff) | |
parent | d089e43b8a03e8a4b1b95a83c044561cfc0290e8 (diff) | |
download | SponsorBlock-032264d8bbd05e295a8f25acc3dc024c67432677.tar.gz SponsorBlock-032264d8bbd05e295a8f25acc3dc024c67432677.zip |
Merge pull request #896 from ajayyy/improvements
More highlight improvements
-rw-r--r-- | public/_locales/en/messages.json | 75 | ||||
-rw-r--r-- | public/content.css | 21 | ||||
-rw-r--r-- | public/help/images/popup.png | bin | 0 -> 55416 bytes | |||
-rw-r--r-- | public/help/images/voting on notice.gif | bin | 0 -> 97468 bytes | |||
-rw-r--r-- | public/help/index.html (renamed from public/help/index_en.html) | 55 | ||||
-rw-r--r-- | public/help/styles.css | 4 | ||||
-rw-r--r-- | public/options/options.css | 4 | ||||
-rw-r--r-- | public/options/options.html | 25 | ||||
-rw-r--r-- | src/background.ts | 6 | ||||
-rw-r--r-- | src/components/CategorySkipOptionsComponent.tsx | 2 | ||||
-rw-r--r-- | src/config.ts | 4 | ||||
-rw-r--r-- | src/content.ts | 15 | ||||
-rw-r--r-- | src/help.ts | 17 | ||||
-rw-r--r-- | src/js-components/skipButtonControlBar.ts | 10 | ||||
-rw-r--r-- | src/options.ts | 5 | ||||
-rw-r--r-- | src/popup.ts | 156 | ||||
-rw-r--r-- | src/render/Tooltip.tsx | 73 | ||||
-rw-r--r-- | src/utils.ts | 1 | ||||
-rw-r--r-- | src/utils/configUtils.ts | 5 | ||||
-rw-r--r-- | webpack/webpack.common.js | 1 |
20 files changed, 367 insertions, 112 deletions
diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 0ba715fe..3e7a3acf 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -19,7 +19,7 @@ "channelWhitelisted": { "message": "Channel Whitelisted!" }, - "Segment": { + "Segment": { "message": "segment" }, "Segments": { @@ -711,6 +711,10 @@ "help": { "message": "Help" }, + "GotIt": { + "message": "Got it", + "description": "Used as the button to dismiss a tooltip" + }, "experiementOptOut": { "message": "Opt-out of all future experiments", "description": "This is used in a popup about a new experiment to get a list of unlisted videos to back up since all unlisted videos uploaded before 2017 will be set to private." @@ -724,5 +728,74 @@ "voteRejectedWarning": { "message": "Vote rejected due to a warning. Click to open a chat to resolve it, or come back later when you have time.", "description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser." + }, + "Donate": { + "message": "Donate" + }, + "hideDonationLink": { + "message": "Hide Donation Link" + }, + "helpPageThanksForInstalling": { + "message": "Thanks for installing SponsorBlock." + }, + "helpPageReviewOptions": { + "message": "Please review the options below" + }, + "helpPageFeatureDisclaimer": { + "message": "Many features are disabled by default. If you want to skip intros, outros, use Invidious, etc., enable them below. You can also hide/show UI elements." + }, + "helpPageHowSkippingWorks": { + "message": "How skipping works" + }, + "helpPageHowSkippingWorks1": { + "message": "Video segments will automatically be skipped if they are found in the database. You can open the popup by clicking the extension icon to get a preview of what they are." + }, + "helpPageHowSkippingWorks2": { + "message": "Whenever you skip a segment, you will get notice. If the timing seems wrong vote down by clicking downvote! You can also vote in the popup." + }, + "Submitting": { + "message": "Submitting" + }, + "helpPageSubmitting1": { + "message": "Submitting can either be done in the popup by hitting the \"Segment Starts Now\" button or in the video player with the buttons on the player." + }, + "helpPageSubmitting2": { + "message": "Clicking the play button indicated the start of a segment and clicking the stop icon indicates the end. You can prepare multiple sponsors before hitting submit. Clicking the upload button will submit. Clicking the garbage can will delete." + }, + "Editing": { + "message": "Editing" + }, + "helpPageEditing1": { + "message": "If you messed up, you can edit or delete your segments after clicking the up arrow button." + }, + "helpPageTooSlow": { + "message": "This is too slow" + }, + "helpPageTooSlow1": { + "message": "There are hotkeys if you want to use them. Press the semicolon key to indicate the start/end of a sponsor segment and click the apostrophe to submit. These can be changed in the options. If you don't use QWERTY, you should probably change the keybinding." + }, + "helpPageCopyOfDatabase": { + "message": "Can I get a copy of the Database? What happens if you disappear?" + }, + "helpPageCopyOfDatabase1": { + "message": "The database is public and available at" + }, + "helpPageCopyOfDatabase2": { + "message": "The source code is freely available. So, even if something happens to me, your submissions are not lost." + }, + "helpPageNews": { + "message": "News and how it is made" + }, + "helpPageSourceCode": { + "message": "Where can I get the source code?" + }, + "Credits": { + "message": "Credits" + }, + "highlightNewFeature": { + "message": "New! Get to the point of the video with one click with the new highlight category" + }, + "LearnMore": { + "message": "Learn More" } } diff --git a/public/content.css b/public/content.css index 54e6cb85..b2e4b1e5 100644 --- a/public/content.css +++ b/public/content.css @@ -518,4 +518,25 @@ input::-webkit-inner-spin-button { bottom: 0px; display: block; margin: auto; +} + +.sponsorBlockTooltip { + position: absolute; + background-color: rgba(28, 28, 28, 0.7); + border-radius: 5px; + padding: 10px; + max-width: 300px; + white-space: normal; + line-height: 1.5em; +} + +.sponsorBlockTooltip::after { + content: " "; + position: absolute; + top: 100%; + left: 15%; + margin-left: -15px; + border-width: 15px; + border-style: solid; + border-color: rgba(28, 28, 28, 0.7) transparent transparent transparent; }
\ No newline at end of file diff --git a/public/help/images/popup.png b/public/help/images/popup.png Binary files differnew file mode 100644 index 00000000..683ad183 --- /dev/null +++ b/public/help/images/popup.png diff --git a/public/help/images/voting on notice.gif b/public/help/images/voting on notice.gif Binary files differnew file mode 100644 index 00000000..f7190201 --- /dev/null +++ b/public/help/images/voting on notice.gif diff --git a/public/help/index_en.html b/public/help/index.html index d6d8d762..31673ee8 100644 --- a/public/help/index_en.html +++ b/public/help/index.html @@ -5,6 +5,9 @@ <meta charset="utf-8"> <link href="styles.css" rel="stylesheet"/> + + <script src="../js/vendor.js"></script> + <script src="../js/help.js"></script> </head> <body> @@ -14,90 +17,92 @@ SponsorBlock </div> - <div class="container"> + <div class="container sponsorBlockPageBody"> - <p class="createdBy">Created By <a href="https://ajay.app">Ajay Ramachandran</a> <img src="https://ajay.app/newprofilepic.jpg" height="30" class="profilepiccircle"/></p> + <p class="createdBy"> + <img src="https://ajay.app/newprofilepic.jpg" height="30" class="profilepiccircle"/> + Created By <a href="https://ajay.app">Ajay Ramachandran</a> + <a href="https://sponsor.ajay.app/donate" target="_blank" rel="noopener" id="sbDonate">(Donate)</a> + </p> <p> - Thanks for installing SponsorBlock. By using this extension, you agree to the <a href="https://gist.github.com/ajayyy/aa9f8ded2b573d4f73a3ffa0ef74f796">Privacy Policy</a> and <a href="https://gist.github.com/ajayyy/9e8100f069348e0bc062641f34d6af12">Terms of Use</a>. + __MSG_helpPageThanksForInstalling__ By using this extension, you agree to the <a href="https://gist.github.com/ajayyy/aa9f8ded2b573d4f73a3ffa0ef74f796">Privacy Policy</a> and <a href="https://gist.github.com/ajayyy/9e8100f069348e0bc062641f34d6af12">Terms of Use</a>. </p> <p> Come contribute, make some suggestions and help out on <a href="https://discord.gg/QnmVMpU">Discord</a> or on <a href="https://matrix.to/#/#sponsor:ajay.app?via=ajay.app&via=matrix.org&via=mozilla.org">Matrix</a>. </p> - <p style="margin-bottom: 0; margin-top: 0" class="bigText center">Please review the options below</p> + <p style="margin-bottom: 0; margin-top: 0" class="bigText center">__MSG_helpPageReviewOptions__</p> <p class="smallText"> - Many features are disabled by default. If you want to skip intros, outros, use Invidious, etc., enable them below. - You can also hide/show UI elements. + __MSG_helpPageFeatureDisclaimer__ </p> <iframe src="../options/options.html#embed" width="100%" height="500px" style="border: none"></iframe> - <h1>How skipping works</h1> + <h1>__MSG_helpPageHowSkippingWorks__</h1> <p class="projectPreview"> <span class="projectPreviewImageLarge"> - <img src="https://i.imgur.com/caf5Bju.png"> + <img src="images/popup.png"> </span> - Video segments will automatically be skipped if they are found in the database. You can open the popup by clicking the extension icon to get a preview of what they are. + __MSG_helpPageHowSkippingWorks1__ <br/> <br/> - Whenever you skip a segment, you will get notice. If the timing seems wrong vote down by clicking downvote! You can also vote in the popup. + __MSG_helpPageHowSkippingWorks2__ </p> - <div class="center"><img height="120px" src="https://user-images.githubusercontent.com/12688112/63067735-5a638700-bede-11e9-8147-f321b57527ec.gif"></div> + <div class="center"><img height="120px" src="images/voting on notice.gif"></div> - <h1>Submitting</h1> + <h1>__MSG_Submitting__</h1> <p class="projectPreview"> <span class="projectPreviewImageLargeRight"> <img src="https://i.imgur.com/A1ilk6x.gif"> </span> - Submitting can either be done in the popup by hitting the "Segment Starts Now" button or in the video player with the buttons on the player. + __MSG_helpPageSubmitting1__ <br/> <br/> - Clicking the play button indicated the start of a segment and clicking the stop icon indicates the end. You can prepare multiple sponsors before hitting submit. Clicking the upload button will submit. Clicking the garbage can will delete. + __MSG_helpPageSubmitting2__ </p> - <h1>Editing</h1> + <h1>__MSG_Editing__</h1> <p class="projectPreview"> <span class="projectPreviewImageLarge"> - <img src="https://i.imgur.com/DZHqbsx.gif"> + <img src="https://wiki.sponsor.ajay.app/images/6/6a/Popup_only.png"> </span> - If you messed up, you can edit or delete your segments in the popup or in the info menu (by hitting the info icon). + __MSG_helpPageEditing1__ </p> - <h1>This is too slow</h1> + <h1>__MSG_helpPageTooSlow__</h1> <p> - There are hotkeys if you want to use them. Press the semicolon key to indicate the start/end of a sponsor segment and click the apostrophe to submit. - These can be changed in the options. If you don't use QWERTY, you should probably change the keybinding. + __MSG_helpPageTooSlow1__ </p> - <h1>Can I get a copy of the Database? What happens if you disappear?</h1> + <h1>__MSG_helpPageCopyOfDatabase__</h1> <p> - The database is public and available at <a href="https://sponsor.ajay.app/database">https://sponsor.ajay.app/database</a>. The source code is freely available. So, even if something happens to me, your submissions are not lost. + __MSG_helpPageCopyOfDatabase1__ <a href="https://sponsor.ajay.app/database">https://sponsor.ajay.app/database</a>. __MSG_helpPageCopyOfDatabase2__ </p> - <h1>News and how it is made</h1> + <h1>__MSG_helpPageNews__</h1> <p> See <a href="https://sponsor.ajay.app/news">https://sponsor.ajay.app/news</a>. </p> - <h1>Where can I get the source code?</h1> + <h1>__MSG_helpPageSourceCode__</h1> <h4 style="display: inline">Client:</h4> <!-- Github logo --> @@ -107,7 +112,7 @@ <!-- Github logo --> <a href="https://github.com/ajayyy/SponsorBlockServer"><svg aria-hidden="true" version="1.1" viewBox="0 0 16 16" height="58px" style="padding-left: 15px"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg></a> - <h1>Credits</h1> + <h1>__MSG_Credits__</h1> <p> Thanks to all <a href="https://github.com/ajayyy/SponsorBlock/graphs/contributors">SponsorBlock contributors</a>, diff --git a/public/help/styles.css b/public/help/styles.css index a7b8b9fd..2e392c2e 100644 --- a/public/help/styles.css +++ b/public/help/styles.css @@ -183,4 +183,8 @@ h1,h2,h3,h4,h5,h6 { svg { text-decoration: none; +} + +#sbDonate { + font-size: 10px; }
\ No newline at end of file diff --git a/public/options/options.css b/public/options/options.css index e6dd3a01..708139ab 100644 --- a/public/options/options.css +++ b/public/options/options.css @@ -364,4 +364,8 @@ svg { background: none; border: none; +} + +#sbDonate { + font-size: 10px; }
\ No newline at end of file diff --git a/public/options/options.html b/public/options/options.html index 90a2e51f..540b5122 100644 --- a/public/options/options.html +++ b/public/options/options.html @@ -19,7 +19,12 @@ </div> <div class="center"> - <p class="createdBy titleBar">__MSG_createdBy__ <a href="https://ajay.app">Ajay Ramachandran</a> <img src="../icons/newprofilepic.jpg" height="30" class="profilepiccircle"/></p> + <p class="createdBy titleBar"> + <img src="../icons/newprofilepic.jpg" height="30" class="profilepiccircle"/> + __MSG_createdBy__ + <a href="https://ajay.app">Ajay Ramachandran</a> + <a href="https://sponsor.ajay.app/donate" target="_blank" rel="noopener" id="sbDonate">(__MSG_Donate__)</a> + </p> <h1>__MSG_Options__</h1> @@ -451,6 +456,24 @@ <br/> <br/> + + <div option-type="toggle" toggle-type="reverse" sync-option="showDonationLink" no-safari="true"> + <label class="switch-container"> + <label class="switch"> + <input type="checkbox" checked> + <span class="slider round"></span> + </label> + <div class="switch-label"> + __MSG_hideDonationLink__ + </div> + </label> + + </div> + + <br/> + <br/> + <br/> + <br/> <div option-type="private-text-change" sync-option="userID" confirm-message="userIDChangeWarning"> <div class="option-button trigger-button"> diff --git a/src/background.ts b/src/background.ts index 70519945..d11abb96 100644 --- a/src/background.ts +++ b/src/background.ts @@ -35,7 +35,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { chrome.tabs.create({url: chrome.runtime.getURL('options/options.html' + (request.hash ? '#' + request.hash : ''))}); return; case "openHelp": - chrome.tabs.create({url: chrome.runtime.getURL('help/index_en.html')}); + chrome.tabs.create({url: chrome.runtime.getURL('help/index.html')}); return; case "openPage": chrome.tabs.create({url: chrome.runtime.getURL(request.url)}); @@ -74,12 +74,14 @@ chrome.runtime.onInstalled.addListener(function () { // If there is no userID, then it is the first install. if (!userID){ //open up the install page - chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")}); + chrome.tabs.create({url: chrome.extension.getURL("/help/index.html")}); //generate a userID const newUserID = utils.generateUserID(); //save this UUID Config.config.userID = newUserID; + + Config.config.highlightCategoryUpdate = false; } }, 1500); }); diff --git a/src/components/CategorySkipOptionsComponent.tsx b/src/components/CategorySkipOptionsComponent.tsx index 1095f5fe..f7baad46 100644 --- a/src/components/CategorySkipOptionsComponent.tsx +++ b/src/components/CategorySkipOptionsComponent.tsx @@ -151,8 +151,6 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr const optionNames = ["disable", "showOverlay", "manualSkip", "autoSkip"]; - console.log(getCategoryActionType(this.props.category)) - for (const optionName of optionNames) { elements.push( <option key={optionName} value={optionName}> diff --git a/src/config.ts b/src/config.ts index f6153a5e..f30dde4d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -38,8 +38,10 @@ interface SBConfig { refetchWhenNotFound: boolean, ytInfoPermissionGranted: boolean, allowExpirements: boolean, + showDonationLink: boolean, autoHideInfoButton: boolean, autoSkipOnMusicVideos: boolean, + highlightCategoryUpdate: boolean // What categories should be skipped categorySelections: CategorySelection[], @@ -181,8 +183,10 @@ const Config: SBObject = { refetchWhenNotFound: true, ytInfoPermissionGranted: false, allowExpirements: true, + showDonationLink: true, autoHideInfoButton: true, autoSkipOnMusicVideos: false, + highlightCategoryUpdate: false, // TODO: Remove this once update is done categorySelections: [{ name: "sponsor" as Category, diff --git a/src/content.ts b/src/content.ts index 804af61d..46a1a1c5 100644 --- a/src/content.ts +++ b/src/content.ts @@ -15,6 +15,7 @@ import { Message, MessageResponse } from "./messageTypes"; import * as Chat from "./js-components/chat"; import { getCategoryActionType } from "./utils/categoryUtils"; import { SkipButtonControlBar } from "./js-components/skipButtonControlBar"; +import { Tooltip } from "./render/Tooltip"; // Hack to get the CSS loaded on permission-based sites (Invidious) utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); @@ -1104,7 +1105,19 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u if (!autoSkip && skippingSegments.length === 1 && getCategoryActionType(skippingSegments[0].category) === CategoryActionType.POI) { - skipButtonControlBar.enable(skippingSegments[0]); + skipButtonControlBar.enable(skippingSegments[0], !Config.config.highlightCategoryUpdate ? 15 : 0); + + if (!Config.config.highlightCategoryUpdate) { + new Tooltip({ + text: chrome.i18n.getMessage("highlightNewFeature"), + link: "https://blog.ajay.app/highlight-sponsorblock", + referenceNode: skipButtonControlBar.getElement().parentElement, + prependElement: skipButtonControlBar.getElement(), + timeout: 15 + }); + + Config.config.highlightCategoryUpdate = true; + } activeSkipKeybindElement?.setShowKeybindHint(false); activeSkipKeybindElement = skipButtonControlBar; diff --git a/src/help.ts b/src/help.ts new file mode 100644 index 00000000..80ac974a --- /dev/null +++ b/src/help.ts @@ -0,0 +1,17 @@ +import Config from "./config"; +import { showDonationLink } from "./utils/configUtils"; + +import Utils from "./utils"; +const utils = new Utils(); + +window.addEventListener('DOMContentLoaded', init); + +async function init() { + utils.localizeHtmlPage(); + + await utils.wait(() => Config.config !== null); + + if (!showDonationLink()) { + document.getElementById("sbDonate").style.display = "none"; + } +}
\ No newline at end of file diff --git a/src/js-components/skipButtonControlBar.ts b/src/js-components/skipButtonControlBar.ts index 9a8af4ec..37a5d409 100644 --- a/src/js-components/skipButtonControlBar.ts +++ b/src/js-components/skipButtonControlBar.ts @@ -18,6 +18,7 @@ export class SkipButtonControlBar { showKeybindHint = true; timeout: NodeJS.Timeout; + duration = 0; skip: (segment: SponsorTime) => void; @@ -42,6 +43,10 @@ export class SkipButtonControlBar { this.container.addEventListener("mouseleave", () => this.startTimer()); } + getElement(): HTMLElement { + return this.container; + } + attachToPage(): void { const leftControlsContainer = document.querySelector(".ytp-left-controls"); this.chapterText = document.querySelector(".ytp-chapter-container"); @@ -51,7 +56,8 @@ export class SkipButtonControlBar { } } - enable(segment: SponsorTime): void { + enable(segment: SponsorTime, duration?: number): void { + if (duration) this.duration = duration; this.segment = segment; this.refreshText(); @@ -78,7 +84,7 @@ export class SkipButtonControlBar { startTimer(): void { this.stopTimer(); - this.timeout = setTimeout(() => this.disable(), Config.config.skipNoticeDuration * 1000); + this.timeout = setTimeout(() => this.disable(), Math.max(Config.config.skipNoticeDuration, this.duration) * 1000); } disable(): void { diff --git a/src/options.ts b/src/options.ts index dad0a52d..8c5c3bca 100644 --- a/src/options.ts +++ b/src/options.ts @@ -6,6 +6,7 @@ window.SB = Config; import Utils from "./utils"; import CategoryChooser from "./render/CategoryChooser"; +import { showDonationLink } from "./utils/configUtils"; const utils = new Utils(); window.addEventListener('DOMContentLoaded', init); @@ -28,6 +29,10 @@ async function init() { await utils.wait(() => Config.config !== null); + if (!showDonationLink()) { + document.getElementById("sbDonate").style.visibility = "hidden"; + } + // Set all of the toggle options to the correct option const optionsContainer = document.getElementById("options"); const optionsElements = optionsContainer.querySelectorAll("*"); diff --git a/src/popup.ts b/src/popup.ts index 092b7db2..0b0664c0 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -3,6 +3,7 @@ import Config from "./config"; import Utils from "./utils"; import { SponsorTime, SponsorHideType } from "./types"; import { Message, MessageResponse } from "./messageTypes"; +import { showDonationLink } from "./utils/configUtils"; const utils = new Utils(); interface MessageListener { @@ -12,7 +13,7 @@ interface MessageListener { class MessageHandler { messageListener: MessageListener; - constructor (messageListener?: MessageListener) { + constructor(messageListener?: MessageListener) { this.messageListener = messageListener; } @@ -107,14 +108,14 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { "sbDonate" ].forEach(id => PageElements[id] = document.getElementById(id)); - // Hide donate button on safari - if (navigator.vendor === "Apple Computer, Inc.") { + // Hide donate button if wanted (Safari, or user choice) + if (!showDonationLink()) { PageElements.sbDonate.style.display = "none"; } //setup click listeners PageElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); - PageElements.whitelistToggle.addEventListener("change", function() { + PageElements.whitelistToggle.addEventListener("change", function () { if (this.checked) { whitelistChannel(); } else { @@ -122,7 +123,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { } }); PageElements.whitelistForceCheck.addEventListener("click", openOptions); - PageElements.toggleSwitch.addEventListener("change", function() { + PageElements.toggleSwitch.addEventListener("change", function () { toggleSkipping(!this.checked); }); PageElements.submitTimes.addEventListener("click", submitTimes); @@ -174,7 +175,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { if (userID != undefined) { //there are probably some views on these submissions then //get the amount of views from the sponsors submitted - utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(response) { + utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function (response) { if (response.status == 200) { const viewCount = JSON.parse(response.responseText).viewCount; if (viewCount != 0) { @@ -191,7 +192,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }); //get this time in minutes - utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(response) { + utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function (response) { if (response.status == 200) { const minutesSaved = JSON.parse(response.responseText).timeSaved; if (minutesSaved != 0) { @@ -237,7 +238,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { getSegmentsFromContentScript(false); function onTabs(tabs, updating: boolean): void { - messageHandler.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) { + messageHandler.sendMessage(tabs[0].id, { message: 'getVideoID' }, function (result) { if (result !== undefined && result.videoID) { currentVideoID = result.videoID; creatingSegment = result.creatingSegment; @@ -262,7 +263,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { messageHandler.sendMessage( tabs[0].id, - {message: 'isInfoFound', updating}, + { message: 'isInfoFound', updating }, infoFound ); } @@ -274,8 +275,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, (tabs) => onTabs(tabs, updating)); } - function infoFound(request: {found: boolean, sponsorTimes: SponsorTime[]}) { - if(chrome.runtime.lastError) { + function infoFound(request: { found: boolean, sponsorTimes: SponsorTime[] }) { + if (chrome.runtime.lastError) { //This page doesn't have the injected content script, or at least not yet displayNoVideo(); return; @@ -306,8 +307,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, - {message: 'isChannelWhitelisted'}, - function(response) { + { message: 'isChannelWhitelisted' }, + function (response) { if (response.value) { PageElements.whitelistChannel.style.display = "none"; PageElements.unwhitelistChannel.style.display = "unset"; @@ -315,7 +316,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { document.querySelectorAll('.SBWhitelistIcon')[0].classList.add("rotated"); } }); - } + } ); } @@ -327,7 +328,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, (tabs) => { messageHandler.sendMessage( tabs[0].id, - {from: 'popup', message: 'sponsorStart'}, + { from: 'popup', message: 'sponsorStart' }, async (response) => { startSponsorCallback(response); @@ -351,7 +352,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }); } - function startSponsorCallback(response: {creatingSegment: boolean}) { + function startSponsorCallback(response: { creatingSegment: boolean }) { creatingSegment = response.creatingSegment; // Only update the segments after a segment was created @@ -364,12 +365,12 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { } //display the video times from the array at the top, in a different section - function displayDownloadedSponsorTimes(request: {found: boolean, sponsorTimes: SponsorTime[]}) { + function displayDownloadedSponsorTimes(request: { found: boolean, sponsorTimes: SponsorTime[] }) { if (request.sponsorTimes != undefined) { // Sort list by start time const segmentTimes = request.sponsorTimes - .sort((a, b) => a.segment[1] - b.segment[1]) - .sort((a, b) => a.segment[0] - b.segment[0]); + .sort((a, b) => a.segment[1] - b.segment[1]) + .sort((a, b) => a.segment[0] - b.segment[0]); //add them as buttons to the issue reporting container const container = document.getElementById("issueReporterTimeButtons"); @@ -388,7 +389,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { categoryColorCircle.style.backgroundColor = Config.config.barTypes[segmentTimes[i].category]?.color; categoryColorCircle.classList.add("dot"); categoryColorCircle.classList.add("sponsorTimesCategoryColorCircle"); - + let extraInfo = ""; if (segmentTimes[i].hidden === SponsorHideType.Downvoted) { //this one is downvoted @@ -397,7 +398,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { //this one is too short extraInfo = " (" + chrome.i18n.getMessage("hiddenDueToDuration") + ")"; } - + const textNode = document.createTextNode(utils.shortCategoryName(segmentTimes[i].category) + extraInfo); const segmentTimeFromToNode = document.createElement("div"); segmentTimeFromToNode.innerText = utils.getFormattedTime(segmentTimes[i].segment[0], true) + " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segmentTimes[i].segment[1], true); @@ -446,7 +447,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { voteButtonsContainer.appendChild(uuidButton); //add click listener to open up vote panel - sponsorTimeButton.addEventListener("click", function() { + sponsorTimeButton.addEventListener("click", function () { voteButtonsContainer.classList.toggle("voteButtonsContainer--hide"); }); @@ -478,15 +479,15 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, - {message: 'submitTimes'}, + { message: 'submitTimes' }, ); }); } } - + function showNoticeAgain() { Config.config.dontShowNotice = false; - + PageElements.showNoticeAgain.style.display = "none"; } @@ -499,11 +500,11 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { //make the options div visible function openOptions() { - chrome.runtime.sendMessage({"message": "openConfig"}); + chrome.runtime.sendMessage({ "message": "openConfig" }); } function openHelp() { - chrome.runtime.sendMessage({"message": "openHelp"}); + chrome.runtime.sendMessage({ "message": "openHelp" }); } //make the options username setting option visible @@ -516,7 +517,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { PageElements.setUsernameContainer.style.display = "none"; PageElements.setUsername.style.display = "flex"; PageElements.setUsername.classList.add("SBExpanded"); - + PageElements.setUsernameStatusContainer.style.display = "none"; PageElements.sponsorTimesContributionsContainer.classList.add("hidden"); @@ -555,18 +556,18 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { function displayNoVideo() { document.getElementById("loadingIndicator").innerText = chrome.i18n.getMessage("noVideoID"); } - + function addVoteMessage(message, UUID) { const voteButtonsContainer = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID); voteButtonsContainer.style.display = "none"; const voteStatusContainer = document.getElementById("sponsorTimesVoteStatusContainer" + UUID); voteStatusContainer.style.removeProperty("display"); - + const thanksForVotingText = document.getElementById("sponsorTimesThanksForVotingText" + UUID); thanksForVotingText.innerText = message; } - + function vote(type, UUID) { //add loading info addVoteMessage(chrome.i18n.getMessage("Loading"), UUID); @@ -597,8 +598,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, - {message: 'getChannelID'}, - function(response) { + { message: 'getChannelID' }, + function (response) { if (!response.channelID) { alert(chrome.i18n.getMessage("channelDataNotFound") + " https://github.com/ajayyy/SponsorBlock/issues/753"); return; @@ -630,10 +631,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, { - message: 'whitelistChange', - value: true - }); - } + message: 'whitelistChange', + value: true + }); + } ); } ); @@ -648,38 +649,38 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, - {message: 'getChannelID'}, - function(response) { + { message: 'getChannelID' }, + function (response) { //get whitelisted channels - let whitelistedChannels = Config.config.whitelistedChannels; - if (whitelistedChannels == undefined) { - whitelistedChannels = []; - } + let whitelistedChannels = Config.config.whitelistedChannels; + if (whitelistedChannels == undefined) { + whitelistedChannels = []; + } + + //remove this channel + const index = whitelistedChannels.indexOf(response.channelID); + whitelistedChannels.splice(index, 1); - //remove this channel - const index = whitelistedChannels.indexOf(response.channelID); - whitelistedChannels.splice(index, 1); - - //change button - PageElements.whitelistChannel.style.display = "unset"; - PageElements.unwhitelistChannel.style.display = "none"; - document.querySelectorAll('.SBWhitelistIcon')[0].classList.remove("rotated"); - - //save this - Config.config.whitelistedChannels = whitelistedChannels; - - //send a message to the client - messageHandler.query({ - active: true, - currentWindow: true - }, tabs => { - messageHandler.sendMessage( - tabs[0].id, { - message: 'whitelistChange', - value: false - }); - } - ); + //change button + PageElements.whitelistChannel.style.display = "unset"; + PageElements.unwhitelistChannel.style.display = "none"; + document.querySelectorAll('.SBWhitelistIcon')[0].classList.remove("rotated"); + + //save this + Config.config.whitelistedChannels = whitelistedChannels; + + //send a message to the client + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, { + message: 'whitelistChange', + value: false + }); + } + ); } ); }); @@ -694,12 +695,13 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }, tabs => { messageHandler.sendMessage( tabs[0].id, - {message: 'refreshSegments'}, + { message: 'refreshSegments' }, (response) => { infoFound(response); stopAnimation(); } - )} + ) + } ); } @@ -707,7 +709,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { * Should skipping be disabled (visuals stay) */ function toggleSkipping(disabled) { - Config.config.disableSkipping = disabled; + Config.config.disableSkipping = disabled; let hiddenButton = PageElements.disableSkipping; let shownButton = PageElements.enableSkipping; @@ -728,13 +730,13 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { * @param {float} seconds * @returns {string} */ - function getFormattedHours(minutes) { - minutes = Math.round(minutes * 10) / 10 - const hours = Math.floor(minutes / 60); - return (hours > 0 ? hours + "h " : "") + (minutes % 60).toFixed(1); - } - -//end of function + function getFormattedHours(minutes) { + minutes = Math.round(minutes * 10) / 10 + const hours = Math.floor(minutes / 60); + return (hours > 0 ? hours + "h " : "") + (minutes % 60).toFixed(1); + } + + //end of function } if (chrome.tabs != undefined) { diff --git a/src/render/Tooltip.tsx b/src/render/Tooltip.tsx new file mode 100644 index 00000000..7bb2e1f3 --- /dev/null +++ b/src/render/Tooltip.tsx @@ -0,0 +1,73 @@ +import * as React from "react"; +import * as ReactDOM from "react-dom"; + +export interface TooltipProps { + text: string, + link?: string, + referenceNode: HTMLElement, + prependElement?: HTMLElement, // Element to append before + bottomOffset?: string + timeout?: number; +} + +export class Tooltip { + text: string; + container: HTMLDivElement; + + timer: NodeJS.Timeout; + + constructor(props: TooltipProps) { + props.bottomOffset ??= "70px"; + this.text = props.text; + + this.container = document.createElement('div'); + this.container.id = "sponsorTooltip" + props.text; + this.container.style.display = "relative"; + + if (props.prependElement) { + props.referenceNode.insertBefore(this.container, props.prependElement); + } else { + props.referenceNode.appendChild(this.container); + } + + if (props.timeout) { + this.timer = setTimeout(() => this.close(), props.timeout * 1000); + } + + ReactDOM.render( + <div style={{bottom: props.bottomOffset}} + className="sponsorBlockTooltip" > + <div> + <img className="sponsorSkipLogo sponsorSkipObject" + src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}> + </img> + <span className="sponsorSkipObject"> + {this.text + (props.link ? ". " : "")} + {props.link ? + <a style={{textDecoration: "underline"}} + target="_blank" + rel="noopener noreferrer" + href={props.link}> + {chrome.i18n.getMessage("LearnMore")} + </a> + : null} + </span> + </div> + <button className="sponsorSkipObject sponsorSkipNoticeButton" + style ={{float: "right" }} + onClick={() => this.close()}> + + {chrome.i18n.getMessage("GotIt")} + </button> + </div>, + this.container + ) + } + + close(): void { + ReactDOM.unmountComponentAtNode(this.container); + this.container.remove(); + + if (this.timer) clearTimeout(this.timer); + } +}
\ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index a40dd5f9..983c1c1b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -261,7 +261,6 @@ export default class Utils { const objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; for (let j = 0; j < objects.length; j++) { const obj = objects[j]; - const localizedMessage = this.getLocalizedMessage(obj.innerHTML.toString()); if (localizedMessage) obj.innerHTML = localizedMessage; } diff --git a/src/utils/configUtils.ts b/src/utils/configUtils.ts new file mode 100644 index 00000000..8aec5208 --- /dev/null +++ b/src/utils/configUtils.ts @@ -0,0 +1,5 @@ +import Config from "../config"; + +export function showDonationLink(): boolean { + return navigator.vendor !== "Apple Computer, Inc." && Config.config.showDonationLink; +}
\ No newline at end of file diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 1d130af0..ccc1c82c 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -10,6 +10,7 @@ module.exports = env => ({ background: path.join(__dirname, srcDir + 'background.ts'), content: path.join(__dirname, srcDir + 'content.ts'), options: path.join(__dirname, srcDir + 'options.ts'), + help: path.join(__dirname, srcDir + 'help.ts'), permissions: path.join(__dirname, srcDir + 'permissions.ts') }, output: { |