source: frontend/src/components/MiniPlayer.tsx@ 615dcee

main
Last change on this file since 615dcee was f5bc95e, checked in by Filip Gavrilovski <filipgavrilovski28@…>, 5 months ago

fix music cover ui bug

  • Property mode set to 100644
File size: 6.1 KB
Line 
1import { baseURL } from "../api/axiosInstance";
2import { usePlayer } from "../context/playerContext";
3
4const MiniPlayer = () => {
5 const { currentSong, isMinimized, stop, toggleMinimize } = usePlayer();
6
7 if (!currentSong) return null;
8
9 return (
10 <>
11 {/* Fullscreen overlay - only visible when not minimized */}
12 <div
13 className={`fixed inset-0 z-100 bg-[#0a0a0f] flex flex-col transition-opacity duration-300 ${
14 isMinimized
15 ? "opacity-0 pointer-events-none"
16 : "opacity-100 pointer-events-auto"
17 }`}
18 >
19 {/* Header bar */}
20 <div className="flex items-center justify-between px-6 py-4 bg-[#1a1a2e]/80 backdrop-blur-sm">
21 <div className="flex items-center gap-4">
22 <img
23 src={
24 currentSong.cover
25 ? `${baseURL}/${currentSong.cover}`
26 : "/favicon.png"
27 }
28 alt={currentSong.title}
29 className="w-12 h-12 rounded-lg object-cover shadow-lg"
30 onError={(e) => {
31 (e.target as HTMLImageElement).src = "/favicon.png";
32 }}
33 />
34 <div>
35 <p className="text-white font-semibold text-lg">
36 {currentSong.title}
37 </p>
38 <p className="text-gray-400 text-sm">{currentSong.artist}</p>
39 </div>
40 </div>
41
42 <div className="flex items-center gap-2">
43 {/* Minimize */}
44 <button
45 onClick={toggleMinimize}
46 className="text-gray-400 hover:text-white p-2.5 rounded-full hover:bg-white/10 transition-all"
47 aria-label="Minimize player"
48 >
49 <svg
50 className="w-6 h-6"
51 fill="none"
52 stroke="currentColor"
53 viewBox="0 0 24 24"
54 >
55 <path
56 strokeLinecap="round"
57 strokeLinejoin="round"
58 strokeWidth={2}
59 d="M19 14l-7 7m0 0l-7-7m7 7V3"
60 />
61 </svg>
62 </button>
63
64 {/* Close */}
65 <button
66 onClick={stop}
67 className="text-gray-400 hover:text-red-400 p-2.5 rounded-full hover:bg-white/10 transition-all"
68 aria-label="Close player"
69 >
70 <svg
71 className="w-6 h-6"
72 fill="none"
73 stroke="currentColor"
74 viewBox="0 0 24 24"
75 >
76 <path
77 strokeLinecap="round"
78 strokeLinejoin="round"
79 strokeWidth={2}
80 d="M6 18L18 6M6 6l12 12"
81 />
82 </svg>
83 </button>
84 </div>
85 </div>
86
87 {/* Video container - visible only in fullscreen */}
88 <div className="flex-1 flex items-center justify-center p-4">
89 <div
90 className={`w-full max-w-5xl aspect-video rounded-xl overflow-hidden shadow-2xl ${
91 isMinimized ? "invisible" : "visible"
92 }`}
93 >
94 {/* Single iframe - always mounted to preserve playback state */}
95 <iframe
96 key={currentSong.embedUrl}
97 src={`${currentSong.embedUrl}?autoplay=1`}
98 title={currentSong.title}
99 className="w-full h-full"
100 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
101 allowFullScreen
102 />
103 </div>
104 </div>
105 </div>
106
107 {/* Minimized bar - always visible at bottom */}
108 <div
109 className={`fixed bottom-0 left-0 right-0 z-100 h-16 bg-[#1a1a2e] border-t border-white/10 shadow-lg transition-transform duration-300 ${
110 isMinimized ? "translate-y-0" : "translate-y-full"
111 }`}
112 >
113 <div className="flex items-center justify-between px-4 h-full max-w-7xl mx-auto">
114 {/* Song info */}
115 <div className="flex items-center gap-3 min-w-0 flex-1">
116 <img
117 src={
118 currentSong.cover
119 ? `${baseURL}/${currentSong.cover}`
120 : "/favicon.png"
121 }
122 alt={currentSong.title}
123 className="w-10 h-10 rounded object-cover shrink-0"
124 onError={(e) => {
125 (e.target as HTMLImageElement).src = "/favicon.png";
126 }}
127 />
128 <div className="min-w-0">
129 <p className="text-white text-sm font-medium truncate">
130 {currentSong.title}
131 </p>
132 <p className="text-gray-400 text-xs truncate">
133 {currentSong.artist}
134 </p>
135 </div>
136 </div>
137
138 {/* Now playing indicator */}
139 <div className="hidden sm:flex items-center gap-1.5 px-4">
140 <div className="flex items-end gap-0.5 h-4">
141 <div
142 className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite]"
143 style={{ height: "60%" }}
144 />
145 <div
146 className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.1s]"
147 style={{ height: "100%" }}
148 />
149 <div
150 className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.2s]"
151 style={{ height: "40%" }}
152 />
153 <div
154 className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.3s]"
155 style={{ height: "80%" }}
156 />
157 </div>
158 <span className="text-[#1db954] text-xs font-medium ml-1">
159 Playing
160 </span>
161 </div>
162
163 {/* Controls */}
164 <div className="flex items-center gap-1">
165 {/* Expand - shows fullscreen to allow seeking */}
166 <button
167 onClick={toggleMinimize}
168 className="text-gray-400 hover:text-white p-2 rounded-full hover:bg-white/10 transition-all"
169 aria-label="Expand player to seek"
170 title="Expand to seek in video"
171 >
172 <svg
173 className="w-5 h-5"
174 fill="none"
175 stroke="currentColor"
176 viewBox="0 0 24 24"
177 >
178 <path
179 strokeLinecap="round"
180 strokeLinejoin="round"
181 strokeWidth={2}
182 d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"
183 />
184 </svg>
185 </button>
186
187 {/* Close */}
188 <button
189 onClick={stop}
190 className="text-gray-400 hover:text-red-400 p-2 rounded-full hover:bg-white/10 transition-all"
191 aria-label="Close player"
192 >
193 <svg
194 className="w-5 h-5"
195 fill="none"
196 stroke="currentColor"
197 viewBox="0 0 24 24"
198 >
199 <path
200 strokeLinecap="round"
201 strokeLinejoin="round"
202 strokeWidth={2}
203 d="M6 18L18 6M6 6l12 12"
204 />
205 </svg>
206 </button>
207 </div>
208 </div>
209 </div>
210 </>
211 );
212};
213
214export default MiniPlayer;
Note: See TracBrowser for help on using the repository browser.