From 82b027159e9b02061ee93374ad3b56a3d6bf3ca7 Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 22 Jun 2022 13:21:44 -0400 Subject: [PATCH] Add UI for importing segments --- public/_locales/en/messages.json | 6 +++++- public/popup.css | 8 ++++++++ public/popup.html | 22 ++++++++++++++++------ src/content.ts | 23 +++++++++++++++++++++++ src/messageTypes.ts | 14 ++++++++++++-- src/popup.ts | 22 ++++++++++++++++++++-- src/utils/exporter.ts | 4 ++-- 7 files changed, 86 insertions(+), 13 deletions(-) diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 49c32662..2653f270 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -1063,6 +1063,10 @@ "message": "Export segments" }, "importSegments": { - "message": "Import segments" + "message": "Import chapters" + }, + "Import": { + "message": "Import", + "description": "Button to initiate importing segments. Appears under the textbox where they paste in the data" } } diff --git a/public/popup.css b/public/popup.css index 5dd0ec5b..c69ab668 100644 --- a/public/popup.css +++ b/public/popup.css @@ -180,6 +180,14 @@ display: block; } +#importSegmentsText { + margin-top: 7px; +} + +#importSegmentsMenu button { + padding: 10px; +} + /* *
wrapper around each segment */ diff --git a/public/popup.html b/public/popup.html index 91b0e0bb..1ded0c27 100644 --- a/public/popup.html +++ b/public/popup.html @@ -45,12 +45,22 @@
diff --git a/src/content.ts b/src/content.ts index b96479b7..340e6ad5 100644 --- a/src/content.ts +++ b/src/content.ts @@ -19,6 +19,7 @@ import { CategoryPill } from "./render/CategoryPill"; import { AnimationUtils } from "./utils/animationUtils"; import { GenericUtils } from "./utils/genericUtils"; import { logDebug } from "./utils/logger"; +import { importTimes } from "./utils/exporter"; // Hack to get the CSS loaded on permission-based sites (Invidious) utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); @@ -231,7 +232,29 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo case "copyToClipboard": navigator.clipboard.writeText(request.text); break; + case "importSegments": { + const importedSegments = importTimes(request.data, video.duration); + let addedSegments = false; + for (const segment of importedSegments) { + if (!sponsorTimesSubmitting.some((s) => s.segment[0] === segment.segment[0] && s.segment[1] === s.segment[1])) { + sponsorTimesSubmitting.push(segment); + addedSegments = true; + } + } + if (addedSegments) { + Config.config.unsubmittedSegments[sponsorVideoID] = sponsorTimesSubmitting; + Config.forceSyncUpdate("unsubmittedSegments"); + + updateEditButtonsOnPlayer(); + updateSponsorTimesSubmitting(false); + } + + sendResponse({ + importedSegments + }); + break; + } } } diff --git a/src/messageTypes.ts b/src/messageTypes.ts index 3d3575cb..99a10f5e 100644 --- a/src/messageTypes.ts +++ b/src/messageTypes.ts @@ -52,7 +52,12 @@ interface CopyToClipboardMessage { text: string; } -export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoFoundMessage | SkipMessage | SubmitVoteMessage | HideSegmentMessage | CopyToClipboardMessage); +interface ImportSegmentsMessage { + message: "importSegments"; + data: string; +} + +export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoFoundMessage | SkipMessage | SubmitVoteMessage | HideSegmentMessage | CopyToClipboardMessage | ImportSegmentsMessage); export interface IsInfoFoundMessageResponse { found: boolean; @@ -83,10 +88,15 @@ export type MessageResponse = | SponsorStartResponse | IsChannelWhitelistedResponse | Record - | VoteResponse; + | VoteResponse + | ImportSegmentsResponse; export interface VoteResponse { successType: number; statusCode: number; responseText: string; +} + +export interface ImportSegmentsResponse { + importedSegments: SponsorTime[]; } \ No newline at end of file diff --git a/src/popup.ts b/src/popup.ts index 9c5cafec..b312e110 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -2,7 +2,7 @@ import Config from "./config"; import Utils from "./utils"; import { SponsorTime, SponsorHideType, ActionType, SegmentUUID, SponsorSourceType } from "./types"; -import { Message, MessageResponse, IsInfoFoundMessageResponse } from "./messageTypes"; +import { Message, MessageResponse, IsInfoFoundMessageResponse, ImportSegmentsResponse } from "./messageTypes"; import { showDonationLink } from "./utils/configUtils"; import { AnimationUtils } from "./utils/animationUtils"; import { GenericUtils } from "./utils/genericUtils"; @@ -143,7 +143,11 @@ async function runThePopup(messageListener?: MessageListener): Promise { "sbCloseButton", "issueReporterImportExport", "importSegmentsButton", - "exportSegmentsButton" + "exportSegmentsButton", + "importSegmentsMenu", + "importSegmentsText", + "importSegmentsSubmit" + ].forEach(id => PageElements[id] = document.getElementById(id)); getSegmentsFromContentScript(false); @@ -174,6 +178,9 @@ async function runThePopup(messageListener?: MessageListener): Promise { } PageElements.exportSegmentsButton.addEventListener("click", exportSegments); + PageElements.importSegmentsButton.addEventListener("click", + () => PageElements.importSegmentsMenu.classList.toggle("hidden")); + PageElements.importSegmentsSubmit.addEventListener("click", importSegments); PageElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); PageElements.whitelistToggle.addEventListener("change", function () { @@ -962,6 +969,17 @@ async function runThePopup(messageListener?: MessageListener): Promise { } } + async function importSegments() { + const text = (PageElements.importSegmentsText as HTMLInputElement).value; + + await sendTabMessage({ + message: "importSegments", + data: text + }) as ImportSegmentsResponse; + + PageElements.importSegmentsMenu.classList.add("hidden"); + } + function exportSegments() { copyToClipboard(exportTimes(downloadedTimes)); diff --git a/src/utils/exporter.ts b/src/utils/exporter.ts index 5de9353c..2620a40f 100644 --- a/src/utils/exporter.ts +++ b/src/utils/exporter.ts @@ -17,9 +17,9 @@ export function exportTimes(segments: SponsorTime[]): string { function exportTime(segment: SponsorTime): string { const name = segment.description || shortCategoryName(segment.category); - return `${GenericUtils.getFormattedTime(segment.segment[0])}${ + return `${GenericUtils.getFormattedTime(segment.segment[0], true)}${ segment.segment[1] && segment.segment[0] !== segment.segment[1] - ? ` - ${GenericUtils.getFormattedTime(segment.segment[1])}` : ""} ${name}`; + ? ` - ${GenericUtils.getFormattedTime(segment.segment[1], true)}` : ""} ${name}`; } export function importTimes(data: string, videoDuration: number): SponsorTime[] {