diff options
author | Ajay <[email protected]> | 2022-06-04 02:01:12 -0400 |
---|---|---|
committer | Ajay <[email protected]> | 2022-06-04 02:01:12 -0400 |
commit | 5545a516be973d01430e5037ec63137c5e409ab7 (patch) | |
tree | 5b34bfd7ff8c8ec86842fe50af5aeead7e7d14fa | |
parent | 0fb2d8df794c17e787e4401cde8510af65d18689 (diff) | |
download | SponsorBlock-5545a516be973d01430e5037ec63137c5e409ab7.tar.gz SponsorBlock-5545a516be973d01430e5037ec63137c5e409ab7.zip |
Added export button
-rw-r--r-- | manifest/manifest.json | 2 | ||||
-rw-r--r-- | public/icons/export.svg | 106 | ||||
-rw-r--r-- | public/icons/import.svg | 91 | ||||
-rw-r--r-- | public/popup.css | 24 | ||||
-rw-r--r-- | public/popup.html | 8 | ||||
-rw-r--r-- | src/popup.ts | 63 |
6 files changed, 266 insertions, 28 deletions
diff --git a/manifest/manifest.json b/manifest/manifest.json index 2b3e0b56..aab3bba8 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -63,6 +63,8 @@ "icons/bolt.svg", "icons/stopwatch.svg", "icons/music-note.svg", + "icons/import.svg", + "icons/export.svg", "icons/PlayerInfoIconSponsorBlocker.svg", "icons/PlayerDeleteIconSponsorBlocker.svg", "popup.html", diff --git a/public/icons/export.svg b/public/icons/export.svg new file mode 100644 index 00000000..337823ab --- /dev/null +++ b/public/icons/export.svg @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Capa_1" + x="0px" + y="0px" + viewBox="0 0 67.671 67.671" + style="enable-background:new 0 0 67.671 67.671;" + xml:space="preserve" + sodipodi:docname="export.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs41" /><sodipodi:namedview + id="namedview39" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="9.309749" + inkscape:cx="33.835499" + inkscape:cy="16.649214" + inkscape:window-width="1366" + inkscape:window-height="731" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="Capa_1" /> +<g + id="g6" + style="fill:#ffffff"> + <path + d="M 52.946,23.348 H 42.834 v 6 h 10.112 c 3.007,0 5.34,1.536 5.34,2.858 v 26.606 c 0,1.322 -2.333,2.858 -5.34,2.858 H 14.724 c -3.007,0 -5.34,-1.536 -5.34,-2.858 V 32.207 c 0,-1.322 2.333,-2.858 5.34,-2.858 h 10.11 v -6 h -10.11 c -6.359,0 -11.34,3.891 -11.34,8.858 v 26.606 c 0,4.968 4.981,8.858 11.34,8.858 h 38.223 c 6.358,0 11.34,-3.891 11.34,-8.858 V 32.207 C 64.286,27.239 59.305,23.348 52.946,23.348 Z" + id="path2" + style="fill:#ffffff" /> + <path + d="m 24.957,14.955 c 0.768,0 1.535,-0.293 2.121,-0.879 l 3.756,-3.756 v 13.028 6 11.494 c 0,1.657 1.343,3 3,3 1.657,0 3,-1.343 3,-3 v -11.494 -6 -13.231 l 3.959,3.959 c 0.586,0.586 1.354,0.879 2.121,0.879 0.767,0 1.535,-0.293 2.121,-0.879 1.172,-1.171 1.172,-3.071 0,-4.242 L 36.078,0.877 C 35.492,0.291 34.725,0 33.958,0 33.95,0 33.943,0 33.935,0 33.927,0 33.92,0 33.912,0 33.145,0 32.378,0.291 31.792,0.877 l -8.957,8.957 c -1.172,1.171 -1.172,3.071 0,4.242 0.587,0.586 1.354,0.879 2.122,0.879 z" + id="path4" + style="fill:#ffffff" /> +</g> +<g + id="g8" + style="fill:#ffffff"> +</g> +<g + id="g10" + style="fill:#ffffff"> +</g> +<g + id="g12" + style="fill:#ffffff"> +</g> +<g + id="g14" + style="fill:#ffffff"> +</g> +<g + id="g16" + style="fill:#ffffff"> +</g> +<g + id="g18" + style="fill:#ffffff"> +</g> +<g + id="g20" + style="fill:#ffffff"> +</g> +<g + id="g22" + style="fill:#ffffff"> +</g> +<g + id="g24" + style="fill:#ffffff"> +</g> +<g + id="g26" + style="fill:#ffffff"> +</g> +<g + id="g28" + style="fill:#ffffff"> +</g> +<g + id="g30" + style="fill:#ffffff"> +</g> +<g + id="g32" + style="fill:#ffffff"> +</g> +<g + id="g34" + style="fill:#ffffff"> +</g> +<g + id="g36" + style="fill:#ffffff"> +</g> +</svg> diff --git a/public/icons/import.svg b/public/icons/import.svg new file mode 100644 index 00000000..b1692f37 --- /dev/null +++ b/public/icons/import.svg @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + version="1.1" + id="Capa_1" + x="0px" + y="0px" + viewBox="0 0 67.671 67.671" + style="enable-background:new 0 0 67.671 67.671;" + xml:space="preserve" + sodipodi:docname="import.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><defs + id="defs41" /><sodipodi:namedview + id="namedview39" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="9.309749" + inkscape:cx="33.835499" + inkscape:cy="33.835499" + inkscape:window-width="1920" + inkscape:window-height="983" + inkscape:window-x="482" + inkscape:window-y="768" + inkscape:window-maximized="1" + inkscape:current-layer="g6" /> +<g + id="g6"> + <path + d="M52.946,23.348H42.834v6h10.112c3.007,0,5.34,1.536,5.34,2.858v26.606c0,1.322-2.333,2.858-5.34,2.858H14.724 c-3.007,0-5.34-1.536-5.34-2.858V32.207c0-1.322,2.333-2.858,5.34-2.858h10.11v-6h-10.11c-6.359,0-11.34,3.891-11.34,8.858v26.606 c0,4.968,4.981,8.858,11.34,8.858h38.223c6.358,0,11.34-3.891,11.34-8.858V32.207C64.286,27.239,59.305,23.348,52.946,23.348z" + id="path2" + style="fill:#ffffff" /> + <path + d="m 42.913,34.887 c -0.768,0 -1.370265,0.528017 -2.121,0.879 l -3.756,3.756 v -19.028 -6 V 3 c 0,-1.657 -1.343,-3 -3,-3 -1.657,0 -3,1.343 -3,3 v 11.494 12 13.231 l -3.959,-3.959 c -0.586,-0.586 -1.354,-0.879 -2.121,-0.879 -0.767,0 -1.535,0.293 -2.121,0.879 -1.172,1.171 -1.172,3.071 0,4.242 l 8.957,8.957 c 0.586,0.586 1.353,0.877 2.12,0.877 h 0.023 0.023 c 0.767,0 1.534,-0.291 2.12,-0.877 l 8.957,-8.957 c 1.172,-1.171 1.172,-3.071 0,-4.242 -0.587,-0.586 -1.354,-0.879 -2.122,-0.879 z" + id="path4" + sodipodi:nodetypes="sscccssscccssccsscssccs" + style="fill:#ffffff" /> +</g> +<g + id="g8"> +</g> +<g + id="g10"> +</g> +<g + id="g12"> +</g> +<g + id="g14"> +</g> +<g + id="g16"> +</g> +<g + id="g18"> +</g> +<g + id="g20"> +</g> +<g + id="g22"> +</g> +<g + id="g24"> +</g> +<g + id="g26"> +</g> +<g + id="g28"> +</g> +<g + id="g30"> +</g> +<g + id="g32"> +</g> +<g + id="g34"> +</g> +<g + id="g36"> +</g> +</svg> diff --git a/public/popup.css b/public/popup.css index ac55cbeb..c6c78064 100644 --- a/public/popup.css +++ b/public/popup.css @@ -148,22 +148,34 @@ margin: 8px; } -/* - * Refresh segments button - */ #refreshSegmentsButton { display: flex; align-items: center; + padding: 5px; + margin: 5px auto; +} + +#refreshSegmentsButton, #issueReporterImportExport button { background: transparent; border-radius: 50%; - margin: 5px auto; border: none; - padding: 5px; } -#refreshSegmentsButton:hover { + +#refreshSegmentsButton:hover, #issueReporterImportExport button:hover { background-color: var(--sb-grey-bg-color); } +#issueReporterImportExport button { + padding: 5px; + margin-right: 15px; + margin-left: 15px; +} + +#issueReporterImportExport img { + width: 24px; + display: block; +} + /* * <details> wrapper around each segment */ diff --git a/public/popup.html b/public/popup.html index 6a47da8a..f8f076ad 100644 --- a/public/popup.html +++ b/public/popup.html @@ -43,6 +43,14 @@ </span> </div> <div id="issueReporterTimeButtons"></div> + <div id="issueReporterImportExport" class="hidden"> + <button id="importSegmentsButton" title="__MSG_importSegments__"> + <img src="/icons/import.svg" alt="Refresh icon" id="importSegments" /> + </button> + <button id="exportSegmentsButton" title="__MSG_exportSegments__"> + <img src="/icons/export.svg" alt="Export icon" id="exportSegments" /> + </button> + </div> </div> </div> diff --git a/src/popup.ts b/src/popup.ts index 48a724d5..7a598281 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -8,6 +8,7 @@ import { AnimationUtils } from "./utils/animationUtils"; import { GenericUtils } from "./utils/genericUtils"; import { shortCategoryName } from "./utils/categoryUtils"; import { localizeHtmlPage } from "./utils/pageUtils"; +import { exportTimes } from "./utils/exporter"; const utils = new Utils(); interface MessageListener { @@ -69,6 +70,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { //the start and end time pairs (2d) let sponsorTimes: SponsorTime[] = []; + let downloadedTimes: SponsorTime[] = []; //current video ID of this tab let currentVideoID = null; @@ -137,7 +139,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { "sbConsiderDonateLink", "sbCloseDonate", "sbBetaServerWarning", - "sbCloseButton" + "sbCloseButton", + "issueReporterImportExport", + "importSegmentsButton", + "exportSegmentsButton" ].forEach(id => PageElements[id] = document.getElementById(id)); getSegmentsFromContentScript(false); @@ -167,7 +172,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { }); } - //setup click listeners + PageElements.exportSegmentsButton.addEventListener("click", exportSegments); + PageElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); PageElements.whitelistToggle.addEventListener("change", function () { if (this.checked) { @@ -441,7 +447,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { } // Sort list by start time - const segmentTimes = request.sponsorTimes + downloadedTimes = request.sponsorTimes .filter((segment) => { if (currentSegmentTab === SegmentTab.Segments) { return segment.actionType !== ActionType.Chapter; @@ -461,12 +467,18 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { container.removeChild(container.firstChild); } + if (downloadedTimes.length > 0) { + PageElements.issueReporterImportExport.classList.remove("hidden"); + } else { + PageElements.issueReporterImportExport.classList.add("hidden"); + } + const isVip = Config.config.isVip; - for (let i = 0; i < segmentTimes.length; i++) { - const UUID = segmentTimes[i].UUID; - const locked = segmentTimes[i].locked; - const category = segmentTimes[i].category; - const actionType = segmentTimes[i].actionType; + for (let i = 0; i < downloadedTimes.length; i++) { + const UUID = downloadedTimes[i].UUID; + const locked = downloadedTimes[i].locked; + const category = downloadedTimes[i].category; + const actionType = downloadedTimes[i].actionType; const segmentSummary = document.createElement("summary"); segmentSummary.className = "segmentSummary"; @@ -478,25 +490,25 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { categoryColorCircle.classList.add("sponsorTimesCategoryColorCircle"); let extraInfo = ""; - if (segmentTimes[i].hidden === SponsorHideType.Downvoted) { + if (downloadedTimes[i].hidden === SponsorHideType.Downvoted) { //this one is downvoted extraInfo = " (" + chrome.i18n.getMessage("hiddenDueToDownvote") + ")"; - } else if (segmentTimes[i].hidden === SponsorHideType.MinimumDuration) { + } else if (downloadedTimes[i].hidden === SponsorHideType.MinimumDuration) { //this one is too short extraInfo = " (" + chrome.i18n.getMessage("hiddenDueToDuration") + ")"; - } else if (segmentTimes[i].hidden === SponsorHideType.Hidden) { + } else if (downloadedTimes[i].hidden === SponsorHideType.Hidden) { extraInfo = " (" + chrome.i18n.getMessage("manuallyHidden") + ")"; } - const name = segmentTimes[i].description || shortCategoryName(category); + const name = downloadedTimes[i].description || shortCategoryName(category); const textNode = document.createTextNode(name + extraInfo); const segmentTimeFromToNode = document.createElement("div"); - if (segmentTimes[i].actionType === ActionType.Full) { + if (downloadedTimes[i].actionType === ActionType.Full) { segmentTimeFromToNode.innerText = chrome.i18n.getMessage("full"); } else { - segmentTimeFromToNode.innerText = GenericUtils.getFormattedTime(segmentTimes[i].segment[0], true) + + segmentTimeFromToNode.innerText = GenericUtils.getFormattedTime(downloadedTimes[i].segment[0], true) + (actionType !== ActionType.Poi - ? " " + chrome.i18n.getMessage("to") + " " + GenericUtils.getFormattedTime(segmentTimes[i].segment[1], true) + ? " " + chrome.i18n.getMessage("to") + " " + GenericUtils.getFormattedTime(downloadedTimes[i].segment[1], true) : ""); } @@ -551,7 +563,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { hideButton.id = "sponsorTimesCopyUUIDButtonContainer" + UUID; hideButton.className = "voteButton"; hideButton.title = chrome.i18n.getMessage("hideSegment"); - if (segmentTimes[i].hidden === SponsorHideType.Hidden) { + if (downloadedTimes[i].hidden === SponsorHideType.Hidden) { hideButton.src = chrome.runtime.getURL("icons/not_visible.svg"); } else { hideButton.src = chrome.runtime.getURL("icons/visible.svg"); @@ -560,12 +572,12 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { const stopAnimation = AnimationUtils.applyLoadingAnimation(hideButton, 0.4); stopAnimation(); - if (segmentTimes[i].hidden === SponsorHideType.Hidden) { + if (downloadedTimes[i].hidden === SponsorHideType.Hidden) { hideButton.src = chrome.runtime.getURL("icons/visible.svg"); - segmentTimes[i].hidden = SponsorHideType.Visible; + downloadedTimes[i].hidden = SponsorHideType.Visible; } else { hideButton.src = chrome.runtime.getURL("icons/not_visible.svg"); - segmentTimes[i].hidden = SponsorHideType.Hidden; + downloadedTimes[i].hidden = SponsorHideType.Hidden; } messageHandler.query({ @@ -576,7 +588,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { tabs[0].id, { message: "hideSegment", - type: segmentTimes[i].hidden, + type: downloadedTimes[i].hidden, UUID: UUID } ); @@ -594,8 +606,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { voteButtonsContainer.appendChild(upvoteButton); voteButtonsContainer.appendChild(downvoteButton); voteButtonsContainer.appendChild(uuidButton); - if (segmentTimes[i].actionType === ActionType.Skip - && [SponsorHideType.Visible, SponsorHideType.Hidden].includes(segmentTimes[i].hidden)) { + if (downloadedTimes[i].actionType === ActionType.Skip + && [SponsorHideType.Visible, SponsorHideType.Hidden].includes(downloadedTimes[i].hidden)) { voteButtonsContainer.appendChild(hideButton); } voteButtonsContainer.appendChild(skipButton); @@ -949,6 +961,13 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> { } } + function exportSegments() { + copyToClipboard(exportTimes(downloadedTimes)); + + const stopAnimation = AnimationUtils.applyLoadingAnimation(PageElements.exportSegmentsButton, 0.3); + stopAnimation(); + } + /** * Converts time in minutes to 2d 5h 25.1 * If less than 1 hour, just returns minutes |