From 371078d15264a43d87afa08010bfa390851053e5 Mon Sep 17 00:00:00 2001 From: hanyd Date: Sun, 15 Dec 2024 22:00:10 +0800 Subject: [PATCH] Sync port video status across button and popup --- src/components/YouTubeLogoButton.tsx | 77 ++++++++++++++++++---------- src/messageTypes.ts | 5 ++ src/popup/PortVideoSection.tsx | 46 +++++++++++------ src/popup/VideoInfo/VideoInfo.tsx | 4 +- src/popup/app.tsx | 15 ++++-- src/render/DesciptionPortPill.tsx | 9 +++- 6 files changed, 106 insertions(+), 50 deletions(-) diff --git a/src/components/YouTubeLogoButton.tsx b/src/components/YouTubeLogoButton.tsx index 7cc07cff..0b362571 100644 --- a/src/components/YouTubeLogoButton.tsx +++ b/src/components/YouTubeLogoButton.tsx @@ -1,36 +1,59 @@ -import { useState } from "react"; import * as React from "react"; +import { PortVideo } from "../types"; interface YouTubeLogoButtonProps { - isBound: boolean; + // isBound: boolean; onClick: () => void; title: string; } -const YouTubeLogoButton: React.FC = ({ isBound, onClick, title }) => { - const [isExpanded, setIsExpanded] = useState(false); - const fillColor = isBound ? "#c76b6b" : "CurrentColor"; - - const handleClick = () => { - setIsExpanded(!isExpanded); - onClick(); - }; - - return ( - - ); -}; +interface YouTubeLogoButtonState { + isExpanded: boolean; + isBound: boolean; +} + +class YouTubeLogoButton extends React.Component { + constructor(props: YouTubeLogoButtonProps) { + super(props); + this.state = { + isExpanded: false, + isBound: false, + }; + this.handleClick = this.handleClick.bind(this); + this.setPortVideo = this.setPortVideo.bind(this); + this.fillColor = this.fillColor.bind(this); + } + + handleClick() { + this.setState({ isExpanded: !this.state.isExpanded }); + this.props.onClick(); + } + + setPortVideo(portVideo: PortVideo) { + this.setState({ isBound: !!portVideo?.UUID }); + } + + private fillColor() { + return this.state.isBound ? "#c76b6b" : "CurrentColor"; + } + + render(): React.ReactNode { + return ( + + ); + } +} export default YouTubeLogoButton; diff --git a/src/messageTypes.ts b/src/messageTypes.ts index 2a5f5d24..e8db53ad 100644 --- a/src/messageTypes.ts +++ b/src/messageTypes.ts @@ -74,6 +74,10 @@ interface SubmitPortVideoMessage { ytbID: string; } +interface GetPortVideoMessage { + message: "getPortVideo"; +} + export type Message = BaseMessage & ( | DefaultMessage @@ -86,6 +90,7 @@ export type Message = BaseMessage & | ImportSegmentsMessage | KeyDownMessage | SubmitPortVideoMessage + | GetPortVideoMessage ); export interface IsInfoFoundMessageResponse { diff --git a/src/popup/PortVideoSection.tsx b/src/popup/PortVideoSection.tsx index dff1c72c..29c16b76 100644 --- a/src/popup/PortVideoSection.tsx +++ b/src/popup/PortVideoSection.tsx @@ -11,6 +11,8 @@ interface PortVideoProps { } interface PortVideoState { + show: boolean; + loading: boolean; portVideo: PortVideo; } @@ -18,12 +20,22 @@ export class PortVideoSection extends React.Component(); + displayNoVideo(): void { + this.setState({ portVideo: null, show: false, loading: false }); + } + + setPortVideo(portVideo: PortVideo): void { + this.setState({ portVideo, show: true, loading: false }); + } + private hasPortVideo(): boolean { return !!this.state.portVideo; } @@ -48,24 +60,28 @@ export class PortVideoSection extends React.Component - {this.hasPortVideo() ? ( + <> + {this.state.show && (
-
{this.state.portVideo.ytbID}
+ {this.hasPortVideo() ? ( +
+
{this.state.portVideo.ytbID}
+
+ ) : ( + <> + + + + )}
- ) : ( - <> - - - )} - + ); } } diff --git a/src/popup/VideoInfo/VideoInfo.tsx b/src/popup/VideoInfo/VideoInfo.tsx index e6a83557..b8223043 100644 --- a/src/popup/VideoInfo/VideoInfo.tsx +++ b/src/popup/VideoInfo/VideoInfo.tsx @@ -4,7 +4,7 @@ import { MessageInstance } from "antd/es/message/interface"; import * as React from "react"; import Config from "../../config"; import { Message, RefreshSegmentsResponse } from "../../messageTypes"; -import { PortVideo, SponsorTime } from "../../types"; +import { SponsorTime } from "../../types"; import { exportTimes } from "../../utils/exporter"; import PopupSegment from "./PopupSegment"; @@ -133,7 +133,7 @@ class VideoInfo extends React.Component { } //display the video times from the array at the top, in a different section - displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], portVideo: PortVideo, time: number) { + displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], time: number) { // Sort list by start time const downloadedTimes = sponsorTimes .sort((a, b) => a.segment[1] - b.segment[1]) diff --git a/src/popup/app.tsx b/src/popup/app.tsx index 3d320c7e..d605ab68 100644 --- a/src/popup/app.tsx +++ b/src/popup/app.tsx @@ -115,7 +115,8 @@ function app() { submitBoxRef.current?.showSubmitBox(); controlMenuRef.current.setState({ hasVideo: true }); - displayDownloadedSponsorTimes(request.sponsorTimes ?? [], request.portVideo ?? null, request.time); + displayDownloadedSponsorTimes(request.sponsorTimes ?? [], request.time); + displayPortVideo(request.portVideo); if (request.found) { videoInfoRef.current.displayVideoWithMessage(); } else if (request.status == 404 || request.status == 200) { @@ -138,14 +139,19 @@ function app() { } //display the video times from the array at the top, in a different section - function displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], portVideo: PortVideo, time: number) { - videoInfoRef.current.displayDownloadedSponsorTimes(sponsorTimes, portVideo, time); + function displayDownloadedSponsorTimes(sponsorTimes: SponsorTime[], time: number) { + videoInfoRef.current.displayDownloadedSponsorTimes(sponsorTimes, time); + } + + function displayPortVideo(portVideo: PortVideo) { + portVideoRef.current?.setPortVideo(portVideo); } /** this is not a Bilibili video page */ function displayNoVideo() { videoInfoRef.current.displayNoVideo(); submitBoxRef.current?.hideSubmitBox(); + portVideoRef.current?.displayNoVideo(); } /** Update Unsubmitted Segments when Config changes */ @@ -229,7 +235,8 @@ function app() { // Clear segments list & start loading animation // We'll get a ping once they're loaded startLoadingAnimation(); - displayDownloadedSponsorTimes([], null, 0); + displayDownloadedSponsorTimes([], 0); + displayPortVideo(null); break; } } diff --git a/src/render/DesciptionPortPill.tsx b/src/render/DesciptionPortPill.tsx index 88caf8c2..3089f794 100644 --- a/src/render/DesciptionPortPill.tsx +++ b/src/render/DesciptionPortPill.tsx @@ -27,6 +27,7 @@ export class DescriptionPortPill { inputContainer: HTMLElement; buttonContainer: HTMLElement; ref: React.RefObject; + buttonRef: React.RefObject; root: Root; constructor( @@ -41,6 +42,8 @@ export class DescriptionPortPill { this.portVideoVote = portVideoVote; this.updateSegments = updateSegments; this.sponsorsLookup = sponsorsLookup; + + this.setPortVideoData = this.setPortVideoData.bind(this); } async setupDecription(videoId: VideoID) { @@ -92,7 +95,8 @@ export class DescriptionPortPill { this.ytbID = portVideo.ytbID; this.portUUID = portVideo.UUID; } - if (this?.ref?.current) this.ref.current.setPortVideoData(portVideo); + waitFor(() => this.ref?.current).then(() => this.ref?.current?.setPortVideoData(portVideo)); + waitFor(() => this.buttonRef?.current).then(() => this.buttonRef?.current?.setPortVideo(portVideo)); } private attachToPage(referenceNode: HTMLElement) { @@ -133,9 +137,10 @@ export class DescriptionPortPill { buttonContainer.id = "bsbPortButton"; const root = createRoot(buttonContainer); + this.buttonRef = React.createRef(); root.render( { this.ref.current.toggleInput(); // toggle display state of the input container