Add UI for importing segments

This commit is contained in:
Ajay
2022-06-22 13:21:44 -04:00
parent c6405fc0c1
commit 82b027159e
7 changed files with 86 additions and 13 deletions

View File

@@ -1063,6 +1063,10 @@
"message": "Export segments" "message": "Export segments"
}, },
"importSegments": { "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"
} }
} }

View File

@@ -180,6 +180,14 @@
display: block; display: block;
} }
#importSegmentsText {
margin-top: 7px;
}
#importSegmentsMenu button {
padding: 10px;
}
/* /*
* <details> wrapper around each segment * <details> wrapper around each segment
*/ */

View File

@@ -45,12 +45,22 @@
</div> </div>
<div id="issueReporterTimeButtons"></div> <div id="issueReporterTimeButtons"></div>
<div id="issueReporterImportExport" class="hidden"> <div id="issueReporterImportExport" class="hidden">
<button id="importSegmentsButton" title="__MSG_importSegments__"> <div id="importExportButtons">
<img src="/icons/import.svg" alt="Refresh icon" id="importSegments" /> <button id="importSegmentsButton" title="__MSG_importSegments__">
</button> <img src="/icons/import.svg" alt="Refresh icon" id="importSegments" />
<button id="exportSegmentsButton" title="__MSG_exportSegments__"> </button>
<img src="/icons/export.svg" alt="Export icon" id="exportSegments" /> <button id="exportSegmentsButton" title="__MSG_exportSegments__">
</button> <img src="/icons/export.svg" alt="Export icon" id="exportSegments" />
</button>
</div>
<span id="importSegmentsMenu" class="hidden">
<textarea id="importSegmentsText" rows="5" style="width:80%"></textarea>
<button id="importSegmentsSubmit" title="__MSG_importSegments__">
__MSG_Import__
</button>
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -19,6 +19,7 @@ import { CategoryPill } from "./render/CategoryPill";
import { AnimationUtils } from "./utils/animationUtils"; import { AnimationUtils } from "./utils/animationUtils";
import { GenericUtils } from "./utils/genericUtils"; import { GenericUtils } from "./utils/genericUtils";
import { logDebug } from "./utils/logger"; import { logDebug } from "./utils/logger";
import { importTimes } from "./utils/exporter";
// Hack to get the CSS loaded on permission-based sites (Invidious) // Hack to get the CSS loaded on permission-based sites (Invidious)
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
@@ -231,7 +232,29 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
case "copyToClipboard": case "copyToClipboard":
navigator.clipboard.writeText(request.text); navigator.clipboard.writeText(request.text);
break; break;
case "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;
}
} }
} }

View File

@@ -52,7 +52,12 @@ interface CopyToClipboardMessage {
text: string; 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 { export interface IsInfoFoundMessageResponse {
found: boolean; found: boolean;
@@ -83,10 +88,15 @@ export type MessageResponse =
| SponsorStartResponse | SponsorStartResponse
| IsChannelWhitelistedResponse | IsChannelWhitelistedResponse
| Record<string, never> | Record<string, never>
| VoteResponse; | VoteResponse
| ImportSegmentsResponse;
export interface VoteResponse { export interface VoteResponse {
successType: number; successType: number;
statusCode: number; statusCode: number;
responseText: string; responseText: string;
} }
export interface ImportSegmentsResponse {
importedSegments: SponsorTime[];
}

View File

@@ -2,7 +2,7 @@ import Config from "./config";
import Utils from "./utils"; import Utils from "./utils";
import { SponsorTime, SponsorHideType, ActionType, SegmentUUID, SponsorSourceType } from "./types"; 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 { showDonationLink } from "./utils/configUtils";
import { AnimationUtils } from "./utils/animationUtils"; import { AnimationUtils } from "./utils/animationUtils";
import { GenericUtils } from "./utils/genericUtils"; import { GenericUtils } from "./utils/genericUtils";
@@ -143,7 +143,11 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
"sbCloseButton", "sbCloseButton",
"issueReporterImportExport", "issueReporterImportExport",
"importSegmentsButton", "importSegmentsButton",
"exportSegmentsButton" "exportSegmentsButton",
"importSegmentsMenu",
"importSegmentsText",
"importSegmentsSubmit"
].forEach(id => PageElements[id] = document.getElementById(id)); ].forEach(id => PageElements[id] = document.getElementById(id));
getSegmentsFromContentScript(false); getSegmentsFromContentScript(false);
@@ -174,6 +178,9 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
} }
PageElements.exportSegmentsButton.addEventListener("click", exportSegments); 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.sponsorStart.addEventListener("click", sendSponsorStartMessage);
PageElements.whitelistToggle.addEventListener("change", function () { PageElements.whitelistToggle.addEventListener("change", function () {
@@ -962,6 +969,17 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
} }
} }
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() { function exportSegments() {
copyToClipboard(exportTimes(downloadedTimes)); copyToClipboard(exportTimes(downloadedTimes));

View File

@@ -17,9 +17,9 @@ export function exportTimes(segments: SponsorTime[]): string {
function exportTime(segment: SponsorTime): string { function exportTime(segment: SponsorTime): string {
const name = segment.description || shortCategoryName(segment.category); 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] 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[] { export function importTimes(data: string, videoDuration: number): SponsorTime[] {