mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
improve playlist pages
This commit is contained in:
parent
66ab5b1e52
commit
9bd1fe9702
@ -8,6 +8,98 @@ import FeedModel from "models/feed"
|
||||
|
||||
import "./index.less"
|
||||
|
||||
const PlaylistsList = (props) => {
|
||||
const hopNumber = props.hopsPerPage ?? 6
|
||||
|
||||
const [offset, setOffset] = React.useState(0)
|
||||
const [ended, setEnded] = React.useState(false)
|
||||
|
||||
const [loading, result, error, makeRequest] = app.cores.api.useRequest(props.fetchMethod, {
|
||||
limit: hopNumber,
|
||||
trim: offset
|
||||
})
|
||||
|
||||
const onClickPrev = () => {
|
||||
if (offset === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
setOffset((value) => value - hopNumber)
|
||||
}
|
||||
|
||||
const onClickNext = () => {
|
||||
if (ended) {
|
||||
return
|
||||
}
|
||||
|
||||
setOffset((value) => value + hopNumber)
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (typeof makeRequest === "function") {
|
||||
makeRequest()
|
||||
}
|
||||
}, [offset])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (result) {
|
||||
setEnded(result.length < hopNumber)
|
||||
}
|
||||
}, [result])
|
||||
|
||||
if (error) {
|
||||
console.error(error)
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<antd.Result
|
||||
status="warning"
|
||||
title="Failed to load"
|
||||
subTitle="We are sorry, but we could not load this requests. Please try again later."
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<div className="playlistExplorer_section_header">
|
||||
<h1>
|
||||
{
|
||||
props.headerIcon
|
||||
}
|
||||
<Translation>
|
||||
{(t) => t(props.headerTitle)}
|
||||
</Translation>
|
||||
</h1>
|
||||
|
||||
<div className="playlistExplorer_section_header_actions">
|
||||
<antd.Button
|
||||
icon={<Icons.MdChevronLeft />}
|
||||
onClick={onClickPrev}
|
||||
disabled={offset === 0 || loading}
|
||||
/>
|
||||
|
||||
<antd.Button
|
||||
icon={<Icons.MdChevronRight />}
|
||||
onClick={onClickNext}
|
||||
disabled={ended || loading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="playlistExplorer_section_list">
|
||||
{
|
||||
loading && <antd.Skeleton active />
|
||||
}
|
||||
{
|
||||
!loading && result.map((playlist, index) => {
|
||||
return <PlaylistItem
|
||||
key={index}
|
||||
playlist={playlist}
|
||||
/>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const PlaylistItem = (props) => {
|
||||
const { playlist } = props
|
||||
|
||||
@ -74,87 +166,6 @@ const RecentlyPlayed = (props) => {
|
||||
</div>
|
||||
}
|
||||
|
||||
const FollowingArtists = (props) => {
|
||||
const [L_MusicFeed, R_MusicFeed, E_MusicFeed] = app.cores.api.useRequest(FeedModel.getPlaylistsFeed)
|
||||
|
||||
if (E_MusicFeed) {
|
||||
console.error(E_MusicFeed)
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<antd.Result
|
||||
status="warning"
|
||||
title="Failed to load"
|
||||
subTitle="We are sorry, but we could not load your playlists. Please try again later."
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<div className="playlistExplorer_section_header">
|
||||
<h1>
|
||||
<Icons.MdPerson />
|
||||
<Translation>
|
||||
{(t) => t("From following artists")}
|
||||
</Translation>
|
||||
</h1>
|
||||
</div>
|
||||
<div className="playlistExplorer_section_list">
|
||||
{
|
||||
L_MusicFeed && <antd.Skeleton active />
|
||||
}
|
||||
{
|
||||
!L_MusicFeed && R_MusicFeed.map((playlist, index) => {
|
||||
return <PlaylistItem
|
||||
key={index}
|
||||
playlist={playlist}
|
||||
/>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const PlaylistExplorer = (props) => {
|
||||
const [L_MusicFeed, R_MusicFeed, E_MusicFeed] = app.cores.api.useRequest(FeedModel.getGlobalMusicFeed)
|
||||
|
||||
if (E_MusicFeed) {
|
||||
console.error(E_MusicFeed)
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<antd.Result
|
||||
status="warning"
|
||||
title="Failed to load"
|
||||
subTitle="We are sorry, but we could not load your playlists. Please try again later."
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <div className="playlistExplorer_section">
|
||||
<div className="playlistExplorer_section_header">
|
||||
<h1>
|
||||
<Icons.MdExplore />
|
||||
<Translation>
|
||||
{(t) => t("Explore from global")}
|
||||
</Translation>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="playlistExplorer_section_list">
|
||||
{
|
||||
L_MusicFeed && <antd.Skeleton active />
|
||||
}
|
||||
{
|
||||
!L_MusicFeed && R_MusicFeed.map((playlist, index) => {
|
||||
return <PlaylistItem
|
||||
key={index}
|
||||
playlist={playlist}
|
||||
/>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const MayLike = (props) => {
|
||||
return <div className="playlistExplorer_section">
|
||||
<div className="playlistExplorer_section_header">
|
||||
@ -180,9 +191,17 @@ export default () => {
|
||||
return <div className="playlistExplorer">
|
||||
<RecentlyPlayed />
|
||||
|
||||
<FollowingArtists />
|
||||
<PlaylistsList
|
||||
headerTitle="From your following artists"
|
||||
headerIcon={<Icons.MdPerson />}
|
||||
fetchMethod={FeedModel.getPlaylistsFeed}
|
||||
/>
|
||||
|
||||
<PlaylistExplorer />
|
||||
<PlaylistsList
|
||||
headerTitle="Explore from global"
|
||||
headerIcon={<Icons.MdExplore />}
|
||||
fetchMethod={FeedModel.getGlobalMusicFeed}
|
||||
/>
|
||||
|
||||
<MayLike />
|
||||
</div>
|
||||
|
@ -4,34 +4,62 @@
|
||||
|
||||
width: 100%;
|
||||
|
||||
max-width: 70vw;
|
||||
|
||||
overflow: visible;
|
||||
gap: 50px;
|
||||
|
||||
.playlistExplorer_section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
margin-bottom: 50px;
|
||||
overflow: visible;
|
||||
|
||||
.playlistExplorer_section_header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
align-items: center;
|
||||
|
||||
margin-bottom: 20px;
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.playlistExplorer_section_header_actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
gap: 10px;
|
||||
|
||||
align-self: center;
|
||||
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.playlistExplorer_section_list {
|
||||
display: flex;
|
||||
//flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
|
||||
max-height: 30vh;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
|
||||
align-items: center;
|
||||
grid-column-gap: 10px;
|
||||
grid-row-gap: 10px;
|
||||
}
|
||||
|
||||
gap: 20px;
|
||||
// add a media query to change the grid-template-columns when the screen can't fit 3 columns
|
||||
@media (max-width: 1500px) {
|
||||
.playlistExplorer_section_list {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
overflow-x: scroll;
|
||||
@media (max-width: 800px) {
|
||||
.playlistExplorer_section_list {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
grid-template-rows: repeat(6, 1fr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,11 +71,11 @@
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
width: 15vw;
|
||||
width: 10vw;
|
||||
height: 10vh;
|
||||
|
||||
min-width: 450px;
|
||||
max-width: 850px;
|
||||
min-width: 400px;
|
||||
max-width: 800px;
|
||||
|
||||
border-radius: 12px;
|
||||
|
||||
@ -99,7 +127,7 @@
|
||||
.playlistItem_info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
width: 100%;
|
||||
max-width: 265px;
|
||||
|
||||
@ -140,7 +168,7 @@
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user