v3: added localization, use global player for uploaded audio/video files
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
useState,
|
||||
} from "react";
|
||||
import { Link, useParams } from "react-router";
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
|
||||
import { API_URL, DEFAULT_PAGE_SIZE } from "../config/api.ts";
|
||||
import { friendlyFetchError } from "../utils/apiError.ts";
|
||||
@@ -74,6 +76,11 @@ export function UserPlaylists() {
|
||||
);
|
||||
|
||||
const [state, setState] = useState<State>({ status: "loading" });
|
||||
const [prevUsername, setPrevUsername] = useState(username);
|
||||
if (prevUsername !== username) {
|
||||
setPrevUsername(username);
|
||||
setState({ status: "loading" });
|
||||
}
|
||||
const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);
|
||||
|
||||
const profileUserId = state.status === "loaded" ? state.profileUser.id : null;
|
||||
@@ -114,7 +121,6 @@ export function UserPlaylists() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!username) return;
|
||||
setState({ status: "loading" });
|
||||
const controller = new AbortController();
|
||||
|
||||
const authHeaders: HeadersInit = token
|
||||
@@ -190,7 +196,7 @@ export function UserPlaylists() {
|
||||
setState({ status: "error", error: friendlyFetchError(err) });
|
||||
});
|
||||
return () => controller.abort();
|
||||
}, [username]);
|
||||
}, [username, cachedCreated, cachedFollowed, token]);
|
||||
|
||||
const loadMoreCreated = useCallback(() => {
|
||||
if (
|
||||
@@ -332,7 +338,7 @@ export function UserPlaylists() {
|
||||
if (state.status === "loading") {
|
||||
return (
|
||||
<PageShell>
|
||||
<p className="page-loading">Loading…</p>
|
||||
<p className="page-loading"><Trans>Loading…</Trans></p>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
@@ -343,7 +349,7 @@ export function UserPlaylists() {
|
||||
message={state.error}
|
||||
actions={
|
||||
<Link to={`/users/${username}`} className="btn-border">
|
||||
← Back to profile
|
||||
<Trans>← Back to profile</Trans>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
@@ -357,7 +363,7 @@ export function UserPlaylists() {
|
||||
<ProfileSubpageHeader
|
||||
username={username!}
|
||||
profileUser={profileUser}
|
||||
title="Playlists"
|
||||
title={t`Playlists`}
|
||||
actions={isOwnProfile && (
|
||||
<NewPlaylistForm
|
||||
toggleClassName="btn-primary"
|
||||
@@ -377,12 +383,13 @@ export function UserPlaylists() {
|
||||
<section className="profile-section">
|
||||
<div className="profile-section-header">
|
||||
<h2 className="profile-section-title">
|
||||
Created ({created.items.length}
|
||||
{created.hasMore ? "+" : ""})
|
||||
<Trans>
|
||||
Created ({created.items.length}{created.hasMore ? "+" : ""})
|
||||
</Trans>
|
||||
</h2>
|
||||
</div>
|
||||
{created.items.length === 0
|
||||
? <p className="empty-state">No playlists yet.</p>
|
||||
? <p className="empty-state"><Trans>No playlists yet.</Trans></p>
|
||||
: (
|
||||
<ul className="dump-feed">
|
||||
{created.items.map((p) => (
|
||||
@@ -399,19 +406,24 @@ export function UserPlaylists() {
|
||||
)}
|
||||
<div ref={createdSentinelRef} />
|
||||
{created.loadingMore && (
|
||||
<p className="feed-loading-more">Loading more…</p>
|
||||
<p className="feed-loading-more"><Trans>Loading more…</Trans></p>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="profile-section">
|
||||
<div className="profile-section-header">
|
||||
<h2 className="profile-section-title">
|
||||
Followed ({followed.items.length}
|
||||
{followed.hasMore ? "+" : ""})
|
||||
<Trans>
|
||||
Followed ({followed.items.length}{followed.hasMore ? "+" : ""})
|
||||
</Trans>
|
||||
</h2>
|
||||
</div>
|
||||
{followed.items.length === 0
|
||||
? <p className="empty-state">No followed playlists yet.</p>
|
||||
? (
|
||||
<p className="empty-state">
|
||||
<Trans>No followed playlists yet.</Trans>
|
||||
</p>
|
||||
)
|
||||
: (
|
||||
<ul className="dump-feed">
|
||||
{followed.items.map((p) => (
|
||||
@@ -421,14 +433,14 @@ export function UserPlaylists() {
|
||||
)}
|
||||
<div ref={followedSentinelRef} />
|
||||
{followed.loadingMore && (
|
||||
<p className="feed-loading-more">Loading more…</p>
|
||||
<p className="feed-loading-more"><Trans>Loading more…</Trans></p>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{confirmDeleteId && (
|
||||
<ConfirmModal
|
||||
message="Delete this playlist? This cannot be undone."
|
||||
confirmLabel="Delete playlist"
|
||||
message={t`Delete this playlist? This cannot be undone.`}
|
||||
confirmLabel={t`Delete playlist`}
|
||||
onConfirm={() => {
|
||||
handleDelete(confirmDeleteId);
|
||||
setConfirmDeleteId(null);
|
||||
|
||||
Reference in New Issue
Block a user