aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/ChapterVoteComponent.tsx
blob: 677a966d17ecfc849ac248819465c5872fcecd87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import * as React from "react";
import Config from "../config";
import { ActionType, Category, SegmentUUID, SponsorTime } from "../types";

import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { VoteResponse } from "../messageTypes";
import { AnimationUtils } from "../../maze-utils/src/animationUtils";
import { Tooltip } from "../render/Tooltip";
import { getErrorMessage } from "../../maze-utils/src/formating";

export interface ChapterVoteProps {
    vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
    size?: string;
}

export interface ChapterVoteState {
    segment?: SponsorTime;
    show: boolean;
    size?: string;
}

class ChapterVoteComponent extends React.Component<ChapterVoteProps, ChapterVoteState> {
    tooltip?: Tooltip;

    constructor(props: ChapterVoteProps) {
        super(props);

        this.state = {
            segment: null,
            show: false,
            size: props.size ?? "22px"
        };
    }

    render(): React.ReactElement {
        if (this.tooltip && !this.state.show) {
            this.tooltip.close();
            this.tooltip = null;
        }

        return (
            <>
                {/* Upvote Button */}
                <button id={"sponsorTimesDownvoteButtonsContainerUpvoteChapter"}
                        className={"playerButton sbPlayerUpvote ytp-button " + (!this.state.show ? "sbhidden" : "")}
                        draggable="false"
                        title={chrome.i18n.getMessage("upvoteButtonInfo")}
                        onClick={(e) => this.vote(e, 1)}>
                    <ThumbsUpSvg className="playerButtonImage" 
                        fill={Config.config.colorPalette.white} 
                        width={this.state.size} height={this.state.size} />
                </button>

                {/* Downvote Button */}
                <button id={"sponsorTimesDownvoteButtonsContainerDownvoteChapter"}
                        className={"playerButton sbPlayerDownvote ytp-button " + (!this.state.show ? "sbhidden" : "")}
                        draggable="false"
                        title={chrome.i18n.getMessage("reportButtonInfo")}
                        onClick={(e) => {
                            const chapterNode = document.querySelector(".ytp-chapter-container") as HTMLElement;

                            if (this.tooltip) {
                                this.tooltip.close();
                                this.tooltip = null;
                            } else {
                                if (this.state.segment?.actionType === ActionType.Chapter) {
                                    const referenceNode = chapterNode?.parentElement?.parentElement;
                                    if (referenceNode) {
                                        const outerBounding = referenceNode.getBoundingClientRect();
                                        const buttonBounding = (e.target as HTMLElement)?.parentElement?.getBoundingClientRect();
                                        
                                        this.tooltip = new Tooltip({
                                            referenceNode: chapterNode?.parentElement?.parentElement,
                                            prependElement: chapterNode?.parentElement,
                                            showLogo: false,
                                            showGotIt: false,
                                            bottomOffset: `${outerBounding.height + 25}px`,
                                            leftOffset: `${buttonBounding.x - outerBounding.x}px`,
                                            extraClass: "centeredSBTriangle",
                                            buttons: [
                                                {
                                                    name: chrome.i18n.getMessage("incorrectVote"),
                                                    listener: (event) => this.vote(event, 0, e.target as HTMLElement).then(() => {
                                                        this.tooltip?.close();
                                                        this.tooltip = null;
                                                    })
                                                }, {
                                                    name: chrome.i18n.getMessage("harmfulVote"),
                                                    listener: (event) => this.vote(event, 30, e.target as HTMLElement).then(() => {
                                                        this.tooltip?.close();
                                                        this.tooltip = null;
                                                    })
                                                }
                                            ]
                                        });
                                    }
                                } else {
                                    this.vote(e, 0, e.target as HTMLElement)
                                }
                            }
                        }}>
                    <ThumbsDownSvg 
                        className="playerButtonImage" 
                        fill={downvoteButtonColor(this.state.segment ? [this.state.segment] : null, SkipNoticeAction.Downvote, SkipNoticeAction.Downvote)} 
                        width={this.state.size} 
                        height={this.state.size} />
                </button>
            </>
        );
    }

    private async vote(event: React.MouseEvent, type: number, element?: HTMLElement): Promise<void> {
        event.stopPropagation();
        if (this.state.segment) {
            const stopAnimation = AnimationUtils.applyLoadingAnimation(element ?? event.currentTarget as HTMLElement, 0.3);

            const response = await this.props.vote(type, this.state.segment.UUID);
            await stopAnimation();

            if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
                this.setState({
                    show: type === 1
                });
            } else if (response.statusCode !== 403) {
                alert(getErrorMessage(response.statusCode, response.responseText));
            }
        }
    }
}

export default ChapterVoteComponent;