11'use client' ;
22
33import {
4+ faCircleNotch ,
45 faDownload ,
6+ faExternalLink ,
57 faHeart ,
68 faPlay ,
79 faPlus ,
@@ -10,7 +12,9 @@ import {
1012import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
1113import { SongViewDtoType } from '@shared/validation/song/dto/types' ;
1214import Image from 'next/image' ;
15+ import Link from 'next/link' ;
1316import { useState } from 'react' ;
17+ import { toast } from 'react-hot-toast' ;
1418
1519import ShareModal from './client/ShareModal' ;
1620import { downloadSongFile , openSongInNBS } from '../util/downloadSong' ;
@@ -110,33 +114,91 @@ const OpenSongInNBSButton = ({
110114 publicId : string ;
111115 } ;
112116} ) => {
117+ const [ loading , setLoading ] = useState ( false ) ;
118+
119+ const setLoadingTimeout = ( timeoutMs : number ) => {
120+ setTimeout ( ( ) => {
121+ setLoading ( false ) ;
122+
123+ if ( ! localStorage . getItem ( 'hideOpenFailedToast' ) ) {
124+ showOpenFailedToast ( ) ;
125+ }
126+ } , timeoutMs ) ;
127+ } ;
128+
113129 return (
114130 < OpenInNBSButton
131+ isLoading = { loading }
115132 handleClick = { ( ) => {
116133 openSongInNBS ( song ) ;
134+ setLoadingTimeout ( 3000 ) ;
135+ setLoading ( true ) ;
117136 } }
118137 />
119138 ) ;
120139} ;
121140
122141const OpenInNBSButton = ( {
142+ isLoading,
123143 handleClick,
124144} : {
145+ isLoading : boolean ;
125146 handleClick : React . MouseEventHandler < HTMLButtonElement > ;
126147} ) => {
127148 return (
128149 < button
129150 onClick = { handleClick }
130- className = 'uppercase px-2 py-1 h-fit rounded-md text-sm bg-blue-600 hover:bg-blue-500'
151+ disabled = { isLoading }
152+ className = 'uppercase px-2 py-1 h-fit rounded-md text-sm bg-blue-600 hover:enabled:bg-blue-500 disabled:opacity-50'
131153 >
132- < div className = 'flex flex-row items-center gap-2' >
133- < FontAwesomeIcon icon = { faPlay } />
154+ < div className = 'flex flex-row items-center gap-2 w-max' >
155+ { isLoading ? (
156+ < FontAwesomeIcon icon = { faCircleNotch } className = 'animate-spin w-3' />
157+ ) : (
158+ < FontAwesomeIcon icon = { faPlay } className = 'w-3' />
159+ ) }
160+
134161 < div > Open in NBS</ div >
135162 </ div >
136163 </ button >
137164 ) ;
138165} ;
139166
167+ const showOpenFailedToast = ( ) => {
168+ toast (
169+ ( t ) => (
170+ < div className = 'flex flex-row items-center justify-center gap-3 w-full text-sm text-white' >
171+ { "Didn't work?" }
172+ < Link
173+ href = 'https://noteblock.studio/'
174+ className = 'bg-blue-500 hover:bg-blue-400 px-2 py-1 ml-2 rounded-md'
175+ >
176+ Download NBS
177+ < FontAwesomeIcon
178+ icon = { faExternalLink }
179+ className = 'w-3 opacity-50 ml-1'
180+ />
181+ </ Link >
182+ < button
183+ className = 'text-blue-500 hover:text-blue-400'
184+ onClick = { ( ) => {
185+ toast . dismiss ( t . id ) ;
186+ localStorage . setItem ( 'hideOpenFailedToast' , 'true' ) ;
187+ } }
188+ >
189+ { "Don't show again" }
190+ </ button >
191+ </ div >
192+ ) ,
193+ {
194+ duration : 5000 ,
195+ style : {
196+ width : '100%' ,
197+ } ,
198+ } ,
199+ ) ;
200+ } ;
201+
140202const DownloadSongButton = ( {
141203 song,
142204} : {
0 commit comments