mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-06 11:37:02 +03:00
Compare commits
2 Commits
3.5.1
...
visual-seg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21f54eef67 | ||
|
|
51d9edbbb4 |
3319
package-lock.json
generated
3319
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
"description": "",
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.1.1",
|
||||
"@types/react": "^16.9.22",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/selenium-webdriver": "^4.0.15",
|
||||
@@ -13,7 +14,8 @@
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"concurrently": "^5.1.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^17.0.2",
|
||||
"svgdom": "^0.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chrome": "0.0.91",
|
||||
|
||||
@@ -305,6 +305,10 @@
|
||||
"mute": {
|
||||
"message": "Mute"
|
||||
},
|
||||
"visual": {
|
||||
"message": "Visual",
|
||||
"description": "This is the name of the option to create visual obstructions on top of the video to hide logos when a skip doesn't work."
|
||||
},
|
||||
"skip_category": {
|
||||
"message": "Skip {0}?"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "react";
|
||||
import * as CompileConfig from "../../config.json";
|
||||
import Config from "../config";
|
||||
import { ActionType, ActionTypes, Category, CategoryActionType, ContentContainer, SponsorTime } from "../types";
|
||||
import { ActionType, Category, CategoryActionType, ContentContainer, SponsorTime } from "../types";
|
||||
import Utils from "../utils";
|
||||
import { getCategoryActionType } from "../utils/categoryUtils";
|
||||
import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
|
||||
|
||||
116
src/components/VisualSegmentEditComponent.tsx
Normal file
116
src/components/VisualSegmentEditComponent.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import * as React from "react";
|
||||
import Config from "../config";
|
||||
import { ContentContainer, VisualSegmentInfo } from "../types";
|
||||
import Utils from "../utils";
|
||||
|
||||
|
||||
const utils = new Utils();
|
||||
|
||||
export interface VisualSegmentEditProps {
|
||||
index: number,
|
||||
|
||||
visual: VisualSegmentInfo,
|
||||
|
||||
idSuffix: string,
|
||||
// Contains functions and variables from the content script needed by the skip notice
|
||||
contentContainer: ContentContainer,
|
||||
}
|
||||
|
||||
export interface VisualSegmentEditState {
|
||||
|
||||
}
|
||||
|
||||
class VisualSegmentEditComponent extends React.Component<VisualSegmentEditProps, VisualSegmentEditState> {
|
||||
|
||||
idSuffix: string;
|
||||
|
||||
configUpdateListener: () => void;
|
||||
|
||||
constructor(props: VisualSegmentEditProps) {
|
||||
super(props);
|
||||
|
||||
this.idSuffix = this.props.idSuffix;
|
||||
|
||||
this.state = {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
// Add as a config listener
|
||||
if (!this.configUpdateListener) {
|
||||
this.configUpdateListener = () => this.configUpdate();
|
||||
Config.configListeners.push(this.configUpdate.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
if (this.configUpdateListener) {
|
||||
Config.configListeners.splice(Config.configListeners.indexOf(this.configUpdate.bind(this)), 1);
|
||||
}
|
||||
}
|
||||
|
||||
render(): React.ReactElement {
|
||||
return <>
|
||||
<span id={`time${this.props.idSuffix}`}>
|
||||
{utils.getFormattedTime(this.props.visual.time, true)}
|
||||
</span>
|
||||
|
||||
<span>
|
||||
-
|
||||
</span>
|
||||
|
||||
{this.getBoundsElement()}
|
||||
|
||||
<span>
|
||||
-
|
||||
</span>
|
||||
|
||||
<input
|
||||
type="checkBox"
|
||||
onChange={(event) => this.colorUpdated(event)}
|
||||
value={this.props.visual.color}
|
||||
/>
|
||||
|
||||
<span>
|
||||
Smooth
|
||||
</span>
|
||||
|
||||
<span>
|
||||
-
|
||||
</span>
|
||||
|
||||
<input
|
||||
className="categoryColorTextBox"
|
||||
type="color"
|
||||
onChange={(event) => this.colorUpdated(event)}
|
||||
value={this.props.visual.color}
|
||||
/>
|
||||
|
||||
|
||||
</>
|
||||
}
|
||||
|
||||
getBoundsElement(): React.ReactElement[] {
|
||||
const elements: React.ReactElement[] = [];
|
||||
|
||||
for (const bound of this.props.visual.bounds) {
|
||||
elements.push(
|
||||
<span>
|
||||
{`${bound[0] * 100}% x ${bound[0] * 100}%, `}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
colorUpdated(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
this.props.visual.color = event.target.value;
|
||||
}
|
||||
|
||||
configUpdate(): void {
|
||||
this.forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
export default VisualSegmentEditComponent;
|
||||
@@ -40,7 +40,9 @@ export class SkipButtonControlBar {
|
||||
this.container.appendChild(this.textContainer);
|
||||
this.container.addEventListener("click", () => this.toggleSkip());
|
||||
this.container.addEventListener("mouseenter", () => this.stopTimer());
|
||||
this.container.addEventListener("mouseenter", () => console.log("mouseenter"));
|
||||
this.container.addEventListener("mouseleave", () => this.startTimer());
|
||||
this.container.addEventListener("mouseleave", () => console.log("mouseleave"));
|
||||
}
|
||||
|
||||
getElement(): HTMLElement {
|
||||
|
||||
15
src/types.ts
15
src/types.ts
@@ -58,11 +58,10 @@ export enum CategoryActionType {
|
||||
|
||||
export enum ActionType {
|
||||
Skip = "skip",
|
||||
Mute = "mute"
|
||||
Mute = "mute",
|
||||
Visual = "visual",
|
||||
}
|
||||
|
||||
export const ActionTypes = [ActionType.Skip, ActionType.Mute];
|
||||
|
||||
export type SegmentUUID = string & { __segmentUUIDBrand: unknown };
|
||||
export type Category = string & { __categoryBrand: unknown };
|
||||
|
||||
@@ -80,6 +79,16 @@ export interface SponsorTime {
|
||||
|
||||
hidden?: SponsorHideType;
|
||||
source?: SponsorSourceType;
|
||||
|
||||
visual: string;
|
||||
}
|
||||
|
||||
export interface VisualSegmentInfo {
|
||||
time: number;
|
||||
bounds: [number, number][];
|
||||
smooth: boolean;
|
||||
curve: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface ScheduledTime extends SponsorTime {
|
||||
|
||||
29
src/utils/visualUtils.ts
Normal file
29
src/utils/visualUtils.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { VisualSegmentInfo } from "../types";
|
||||
import { Svg, SVG } from "@svgdotjs/svg.js";
|
||||
|
||||
export function toSVG(visuals: VisualSegmentInfo[]): Svg {
|
||||
const svg = SVG().size(100, 100);
|
||||
|
||||
for (const visual of visuals) {
|
||||
const path = svg.polygon();
|
||||
path.fill(visual.color);
|
||||
// path.stroke({
|
||||
// width: 1,
|
||||
// color: visual.color
|
||||
// });
|
||||
path.plot(visual.bounds);
|
||||
}
|
||||
|
||||
console.log(svg.svg());
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
export function toVisualSegmentInfo(svgInput: string | Svg): VisualSegmentInfo {
|
||||
let svg = svgInput as Svg;
|
||||
if (typeof svgInput === "string") {
|
||||
svg = SVG().svg(svgInput);
|
||||
}
|
||||
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
21
test/visualSegments.test.ts
Normal file
21
test/visualSegments.test.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
import { createSVGWindow } from "svgdom";
|
||||
import { registerWindow } from "@svgdotjs/svg.js";
|
||||
|
||||
import { toSVG } from "../src/utils/visualUtils";
|
||||
|
||||
beforeAll(() => {
|
||||
const window = createSVGWindow();
|
||||
registerWindow(window, window.document)
|
||||
})
|
||||
|
||||
test("Visual Segment SVG converter", async () => {
|
||||
toSVG([{
|
||||
time: 0,
|
||||
bounds: [[0, 0], [25, 0], [25, 40], [0, 30]],
|
||||
smooth: false,
|
||||
curve: "linear",
|
||||
color: "#000000",
|
||||
}]);
|
||||
});
|
||||
Reference in New Issue
Block a user