1+ import axios from 'axios' ;
12import React , { useEffect , useState } from 'react' ;
23import ClipLoader from 'react-spinners/ClipLoader' ;
34import { vtuberInfo } from './DisplayMyLivers' ;
45import LiveStatus from './DisplayedLiver/LiveStatus' ;
56
7+ import { BookmarkIcon , BookmarkSlashIcon } from '@heroicons/react/24/solid' ;
68import { AiFillTwitterCircle } from 'react-icons/ai' ;
79
810export function DisplayedLiver ( {
911 member,
1012 loading,
13+ path,
1114} : {
12- member : vtuberInfo ;
15+ member : any ;
1316 loading : boolean ;
17+ path : string ;
1418} ) {
1519 const [ showLiveStatus , setShowLiveStatus ] = useState ( false ) ;
20+ const [ customList , setCustomList ] = useState < any > ( { } ) ;
21+ const [ fetchingVTuber , setFetchingVTuber ] = useState ( false ) ;
22+
23+ function checkMyLivers ( ) {
24+ chrome . storage . local . get ( [ 'myLivers' , 'customList' ] , function ( data ) {
25+ setCustomList ( data . customList ) ;
26+ } ) ;
27+ }
28+
29+ useEffect ( ( ) => {
30+ if ( path === 'viewAll' ) checkMyLivers ( ) ;
31+ } , [ ] ) ;
32+
33+ const deleteFromMyLivers = ( channelID : string ) => {
34+ let tempCustomList = customList ;
35+ delete tempCustomList [ channelID ] ;
36+ chrome . storage . local . set ( { customList : tempCustomList } ) ;
37+ setCustomList ( tempCustomList ) ;
38+ } ;
39+
40+ const addToMyLivers = async ( channelID : string ) => {
41+ let vtuberTwitter = '' ;
42+ setFetchingVTuber ( true ) ;
43+ const config = {
44+ url : `https://holodex.net/api/v2/channels/${ channelID } ` ,
45+ headers : {
46+ 'X-APIKEY' : process . env . NEXT_PUBLIC_HOLODEX ,
47+ 'Content-Type' : 'application/json' ,
48+ } ,
49+ } ;
50+ try {
51+ const { data } = await axios . request ( config ) ;
52+ vtuberTwitter = data . twitter ;
53+ setFetchingVTuber ( false ) ;
54+ } catch ( error ) {
55+ console . log ( error ) ;
56+ }
57+
58+ let tempCustomList = customList ;
59+
60+ tempCustomList = {
61+ ...tempCustomList ,
62+ [ channelID ] : {
63+ name : member . channel . english_name ,
64+ imageURL : member . channel . photo ,
65+ channelID : member . channel . id ,
66+ twitter : vtuberTwitter ,
67+ status : member . status ,
68+ title : member . title ,
69+ started : member . start_actual ,
70+ org : member . channel . org ,
71+ viewers : member . live_viewers ,
72+ } ,
73+ } ;
74+ chrome . storage . local . set ( { customList : tempCustomList } ) ;
75+ setCustomList ( tempCustomList ) ;
76+ } ;
1677
1778 function handleTwitter ( twitterID : string ) {
1879 const url = 'https://twitter.com/' ;
1980 chrome . tabs . create ( { url : url + twitterID } ) ;
2081 }
2182
22- const url = `https://youtube.com/channel/${ member . channelID } /live` ;
83+ const url = `https://youtube.com/channel/${
84+ member . channelID || member . channel . id
85+ } /live`;
2386 const isLive = member . status === 'live' ;
2487
2588 return (
@@ -35,8 +98,8 @@ export function DisplayedLiver({
3598 } }
3699 >
37100 < img
38- src = { member . imageURL }
39- alt = { member . name }
101+ src = { member . imageURL || member . channel . photo }
102+ alt = { member . name || member . channel . english_name }
40103 className = { `rounded-full h-20 liver border-4 ${
41104 isLive
42105 ? 'border-red-500'
@@ -46,7 +109,7 @@ export function DisplayedLiver({
46109 chrome . tabs . create ( { url : url } ) ;
47110 } }
48111 />
49- { ! loading && (
112+ { ! loading && member . twitter && (
50113 < div
51114 className = { `${
52115 isLive
@@ -63,7 +126,26 @@ export function DisplayedLiver({
63126 > </ span >
64127 </ div >
65128 ) }
66-
129+ { path === 'viewAll' && ! fetchingVTuber && (
130+ < div className = "absolute left-[4.8em] bottom-[4.8em] rounded-full fade-in text-red-500" >
131+ { Object . keys ( customList ) . includes ( member . channel . id ) ? (
132+ < BookmarkSlashIcon
133+ onClick = { ( ) => deleteFromMyLivers ( member . channel . id ) }
134+ className = "h-5 w-5 p-0.5 bg-white border-2 hover:text-red-300 border-red-500 rounded-full cursor-pointer"
135+ />
136+ ) : (
137+ < BookmarkIcon
138+ onClick = { ( ) => addToMyLivers ( member . channel . id ) }
139+ className = "h-5 w-5 p-0.5 text-black hover:text-neutral-800 bg-white border-2 border-red-500 rounded-full cursor-pointer"
140+ />
141+ ) }
142+ </ div >
143+ ) }
144+ { fetchingVTuber && (
145+ < div className = "absolute left-[4.7em] bottom-[4.6em] bg-red-500 p-1 pb-0 rounded-full fade-in" >
146+ < ClipLoader size = { 15 } color = "white" />
147+ </ div >
148+ ) }
67149 { loading && (
68150 < div >
69151 < div className = "absolute left-[4.5em] bottom-[4.5em] bg-white p-1 pb-0 rounded-full dark:bg-slate-700 fade-in" >
0 commit comments