TRip changes/AudioPlayer hls setting tweaks
This commit is contained in:
@@ -84,8 +84,8 @@ export default function Player() {
|
||||
const hls = new Hls({
|
||||
lowLatencyMode: true,
|
||||
abrEnabled: false,
|
||||
liveSyncDuration: 3, // seconds behind live edge target
|
||||
liveMaxLatencyDuration: 10, // max allowed latency before catchup
|
||||
liveSyncDuration: 2.5, // seconds behind live edge target
|
||||
liveMaxLatencyDuration: 3.5, // max allowed latency before catchup
|
||||
liveCatchUpPlaybackRate: 1.05, // playback speed when catching up
|
||||
});
|
||||
|
||||
|
@@ -38,6 +38,14 @@ export default function LoginPage() {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
if (!username) {
|
||||
setLoading(false);
|
||||
return toast.error("Username is required");
|
||||
}
|
||||
if (!password) {
|
||||
setLoading(false);
|
||||
return toast.error("Password is required");
|
||||
}
|
||||
const formData = new URLSearchParams();
|
||||
formData.append("username", username);
|
||||
formData.append("password", password);
|
||||
@@ -113,7 +121,7 @@ export default function LoginPage() {
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
autoComplete="username"
|
||||
autoComplete="off"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
required
|
||||
@@ -134,7 +142,7 @@ export default function LoginPage() {
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
autoComplete="current-password"
|
||||
autoComplete="off"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
|
@@ -19,6 +19,8 @@ export default function MediaRequestForm() {
|
||||
const [artistSuggestions, setArtistSuggestions] = useState([]);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [loadingAlbumId, setLoadingAlbumId] = useState(null);
|
||||
const [expandedAlbums, setExpandedAlbums] = useState([]);
|
||||
|
||||
const debounceTimeout = useRef(null);
|
||||
const autoCompleteRef = useRef(null);
|
||||
@@ -33,6 +35,13 @@ export default function MediaRequestForm() {
|
||||
};
|
||||
|
||||
|
||||
const Spinner = () => (
|
||||
<span
|
||||
className="inline-block ml-2 h-4 w-4 border-2 border-t-2 border-gray-300 border-t-blue-600 rounded-full animate-spin"
|
||||
aria-label="Loading"
|
||||
/>
|
||||
);
|
||||
|
||||
// Fetch artist suggestions for autocomplete
|
||||
const searchArtists = (e) => {
|
||||
const query = e.query.trim();
|
||||
@@ -114,6 +123,7 @@ export default function MediaRequestForm() {
|
||||
|
||||
setAlbums(data);
|
||||
setTracksByAlbum({});
|
||||
setExpandedAlbums([]);
|
||||
|
||||
// Set selectedTracks for all albums as null (means tracks loading/not loaded)
|
||||
setSelectedTracks(
|
||||
@@ -197,16 +207,17 @@ export default function MediaRequestForm() {
|
||||
let isCancelled = false;
|
||||
|
||||
const albumsToFetch = albums.filter((a) => !tracksByAlbum[a.id]);
|
||||
|
||||
if (albumsToFetch.length === 0) return;
|
||||
|
||||
const fetchTracksSequentially = async () => {
|
||||
for (const album of albumsToFetch) {
|
||||
if (isCancelled) break;
|
||||
|
||||
setLoadingAlbumId(album.id);
|
||||
|
||||
try {
|
||||
const res = await authFetch(
|
||||
`${API_URL}/trip/get_tracks_by_album_id/${album.id}`
|
||||
);
|
||||
const res = await authFetch(`${API_URL}/trip/get_tracks_by_album_id/${album.id}`);
|
||||
if (!res.ok) throw new Error("API error");
|
||||
const data = await res.json();
|
||||
|
||||
@@ -223,6 +234,7 @@ export default function MediaRequestForm() {
|
||||
setSelectedTracks((prev) => ({ ...prev, [album.id]: [] }));
|
||||
}
|
||||
}
|
||||
setLoadingAlbumId(null);
|
||||
};
|
||||
|
||||
fetchTracksSequentially();
|
||||
@@ -232,6 +244,7 @@ export default function MediaRequestForm() {
|
||||
};
|
||||
}, [albums, type]);
|
||||
|
||||
|
||||
// Toggle individual track checkbox
|
||||
const toggleTrack = (albumId, trackId) => {
|
||||
setSelectedTracks((prev) => {
|
||||
@@ -390,7 +403,12 @@ export default function MediaRequestForm() {
|
||||
|
||||
{type === "artist" && albums.length > 0 && (
|
||||
<>
|
||||
<Accordion multiple className="mt-4">
|
||||
<Accordion
|
||||
multiple
|
||||
className="mt-4"
|
||||
activeIndex={expandedAlbums}
|
||||
onTabChange={(e) => setExpandedAlbums(e.index)}
|
||||
>
|
||||
{albums.map(({ album, id, release_date }) => {
|
||||
const allTracks = tracksByAlbum[id] || [];
|
||||
const selected = selectedTracks[id];
|
||||
@@ -418,10 +436,14 @@ export default function MediaRequestForm() {
|
||||
className="cursor-pointer"
|
||||
aria-label={`Select all tracks for album ${album}`}
|
||||
/>
|
||||
<span>{album}</span>
|
||||
<span className="flex items-center">
|
||||
{album}
|
||||
{loadingAlbumId === id && <Spinner />}
|
||||
</span>
|
||||
<small className="ml-2 text-neutral-500 dark:text-neutral-400">({release_date})</small>
|
||||
</div>
|
||||
}
|
||||
|
||||
>
|
||||
{allTracks.length > 0 ? (
|
||||
<ul className="text-sm">
|
||||
|
Reference in New Issue
Block a user