mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-06 19:47:04 +03:00
Add UI for importing segments
This commit is contained in:
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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[];
|
||||||
|
}
|
||||||
22
src/popup.ts
22
src/popup.ts
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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[] {
|
||||||
|
|||||||
Reference in New Issue
Block a user