mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 19:14:16 +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"
|
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 PlaylistItem = (props) => {
|
||||||
const { playlist } = props
|
const { playlist } = props
|
||||||
|
|
||||||
@ -74,87 +166,6 @@ const RecentlyPlayed = (props) => {
|
|||||||
</div>
|
</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) => {
|
const MayLike = (props) => {
|
||||||
return <div className="playlistExplorer_section">
|
return <div className="playlistExplorer_section">
|
||||||
<div className="playlistExplorer_section_header">
|
<div className="playlistExplorer_section_header">
|
||||||
@ -180,9 +191,17 @@ export default () => {
|
|||||||
return <div className="playlistExplorer">
|
return <div className="playlistExplorer">
|
||||||
<RecentlyPlayed />
|
<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 />
|
<MayLike />
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,34 +4,62 @@
|
|||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
max-width: 70vw;
|
gap: 50px;
|
||||||
|
|
||||||
overflow: visible;
|
|
||||||
|
|
||||||
.playlistExplorer_section {
|
.playlistExplorer_section {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
margin-bottom: 50px;
|
overflow: visible;
|
||||||
|
|
||||||
.playlistExplorer_section_header {
|
.playlistExplorer_section_header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.5rem;
|
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 {
|
.playlistExplorer_section_list {
|
||||||
display: flex;
|
display: grid;
|
||||||
//flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
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;
|
cursor: pointer;
|
||||||
|
|
||||||
width: 15vw;
|
width: 10vw;
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
|
|
||||||
min-width: 450px;
|
min-width: 400px;
|
||||||
max-width: 850px;
|
max-width: 800px;
|
||||||
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|
||||||
@ -99,7 +127,7 @@
|
|||||||
.playlistItem_info {
|
.playlistItem_info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 265px;
|
max-width: 265px;
|
||||||
|
|
||||||
@ -140,7 +168,7 @@
|
|||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user