Skip to content

Commit

Permalink
started song player global state
Browse files Browse the repository at this point in the history
  • Loading branch information
huilensolis committed Oct 27, 2023
1 parent 3a43136 commit 329411a
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 31 deletions.
20 changes: 13 additions & 7 deletions src/app/(site)/song/[id]/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
'use client'

import { Header, SongCard } from '@components'
import { useLoadImages, useGetSongById } from '@hooks'
import { TriangleIcon } from '@icons'
import { Header, SongCard, PlayBtn } from '@components'
import { useLoadImages, useGetSongById, useOnPlay } from '@hooks'

export function SongDetails({ songId }: { songId: string }) {
const { song, isLoading } = useGetSongById(songId)

const imagePath = useLoadImages(song)

const onPlay = useOnPlay([song!])

function handleOnPlay(id: string) {
onPlay(id)
}
return (
<>
<Header>
Expand Down Expand Up @@ -36,10 +41,11 @@ export function SongDetails({ songId }: { songId: string }) {
<SongCard
song={song}
rightSide={
<figure className="aspect-square h-full w-[calc(0.5rem*2+4rem)] p-2 hidden group-hover:md:flex items-center justify-center">
<div className="h-3/4 w-3/4 bg-green-500 rounded-full transition-all delay-75 flex justify-center items-center hover:scale-105">
<TriangleIcon className="fill-neutral-900 transition-all delay-75 w-6 h-6 text-center flex justify-center items-center" />
</div>
<figure className="aspect-square h-[70px] w-[70px] p-1 hidden group-hover:md:flex items-center justify-center">
<PlayBtn
songs={[song]}
onPlay={() => handleOnPlay(song.id)}
/>
</figure>
}
/>
Expand Down
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export * from './search-songs'
export * from './like-button'
export * from './favorite-songs'
export * from './user-songs'
export * from './player'
export * from './player'
export * from './play-btn'
27 changes: 18 additions & 9 deletions src/components/library/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
'use client'

import { DiscIcon, PLusIcon, TriangleIcon } from '@icons'
import { DiscIcon, PLusIcon } from '@icons'
import { type Song } from '@models'
import { SongCard } from '@components'
import { useAuthModalStore, useUploadModalStore, useUser } from '@hooks'
import { PlayBtn, SongCard } from '@components'
import {
useAuthModalStore,
useOnPlay,
useUploadModalStore,
useUser,
} from '@hooks'

export function Library({ songs }: { songs: Song[] }) {
const { open: openAuthModal } = useAuthModalStore()
const { open: openUploadModal } = useUploadModalStore()
const { user } = useUser()

const onPlay = useOnPlay(songs)

const handleOnclick = () => {
// we check the user is logged
if (!user) {
Expand All @@ -21,6 +28,10 @@ export function Library({ songs }: { songs: Song[] }) {
return
}

function handleOnPlay(id: string) {
onPlay(id)
}

return (
<section className="flex flex-col gap-4 w-full h-full">
<header className="flex gap-4 justify-between px-2">
Expand All @@ -39,19 +50,17 @@ export function Library({ songs }: { songs: Song[] }) {
<SongCard
song={song}
rightSide={
<figure className="aspect-square h-full w-[calc(0.5rem*2+4rem)] p-2 hidden group-hover:md:flex items-center justify-center">
<div className="h-3/4 w-3/4 bg-green-500 rounded-full transition-all delay-75 flex justify-center items-center hover:scale-105">
<TriangleIcon className="fill-neutral-900 transition-all delay-75 w-6 h-6 text-center flex justify-center items-center" />
</div>
</figure>
<PlayBtn
onPlay={() => handleOnPlay(song.id)}
/>
}
/>
</li>
))}
{songs.length === 0 && (
<li>
<span className="text-neutral-400">
no songs available
no songs available.
</span>
</li>
)}
Expand Down
20 changes: 20 additions & 0 deletions src/components/play-btn/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client'

import { TriangleIcon } from '@icons'

export function PlayBtn({
onPlay,
}: {
onPlay: () => void
}) {
return (
<button
className="aspect-square h-full w-full flex items-center justify-center"
onClick={onPlay}
>
<div className="h-full w-full bg-green-500 rounded-full transition-all delay-75 flex justify-center items-center hover:scale-105">
<TriangleIcon className="fill-neutral-900 transition-all delay-75 w-6 h-6 text-center flex justify-center items-center" />
</div>
</button>
)
}
14 changes: 9 additions & 5 deletions src/components/player/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
'use client'

import { usePlayerStore } from '@hooks'
import { useGetSongById, useLoadSongUrl, usePlayerStore } from '@hooks'

export function Player() {
const player = usePlayerStore()

const { song, isLoading } = useGetSongById(player.activeId ?? null)

const songUrl = useLoadSongUrl(song!)

if (!song || isLoading || !player.activeId || !songUrl) return null

return (
<section className="flex items-center justify-center bg-neutral-950 absolute bottom-0 left-0 h-44 w-full">
player
<section className="flex items-center justify-center bg-neutral-950 fixed bottom-0 left-0 h-20 w-full py-2 px-2">
<h4>{song.title}</h4>
</section>
)
}


13 changes: 12 additions & 1 deletion src/components/song-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
'use client'

import { Song } from '@models'
import { SquareSongCard } from '@components'
import { useOnPlay } from '@hooks'

export function SongList({ songs }: { songs: Song[] }) {
const onPlayHook = useOnPlay(songs)

function onPlay(songId: string) {
onPlayHook(songId)
}
return (
<ul className="flex flex-wrap md:gap-4 gap-2 md:p-6 p-2 w-full 350px:justify-normal justify-center">
{songs.length >= 1 ? (
songs.map((song) => (
<li key={song.id}>
<SquareSongCard song={song} />
<SquareSongCard
song={song}
onPlay={() => onPlay(song.id)}
/>
</li>
))
) : (
Expand Down
17 changes: 11 additions & 6 deletions src/components/square-song-card/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
'use client'

import { Song } from '@models'
import { useLoadImages } from '@hooks'
import { TriangleIcon } from '@icons'
import Link from 'next/link'
import { PlayBtn } from '@components'

export function SquareSongCard({ song }: { song: Song }) {
export function SquareSongCard({
song,
onPlay,
}: {
song: Song
onPlay: () => void
}) {
const imagePath = useLoadImages(song)
return (
<Link href={`/song/${song.id}`}>
Expand All @@ -16,10 +23,8 @@ export function SquareSongCard({ song }: { song: Song }) {
alt={song.title}
className="w-full h-full object-cover rounded-md"
/>
<figure className="aspect-square h-[70px] w-[70px] p-1 absolute right-0 bottom-0 hidden group-hover:md:flex items-center justify-center">
<div className="h-full w-full bg-green-500 rounded-full transition-all delay-75 flex justify-center items-center hover:scale-105">
<TriangleIcon className="fill-neutral-900 transition-all delay-75 w-6 h-6 text-center flex justify-center items-center" />
</div>
<figure className="aspect-square h-[70px] w-[70px] p-1 absolute right-0 bottom-0 hidden group-hover:md:flex items-center justify-center z-10">
<PlayBtn onPlay={onPlay} />
</figure>
</div>
<section className="flex flex-col justify-between">
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/get-song-by-id/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use client'

import { useSessionContext } from '@supabase/auth-helpers-react'
import { useEffect, useMemo, useState } from 'react'
import toast from 'react-hot-toast'

import { Song } from '@models'

export function useGetSongById(id: string) {
export function useGetSongById(id: string | null) {
const [song, setSong] = useState<Song | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(false)

Expand Down
4 changes: 3 additions & 1 deletion src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ export * from './auth-modal-store'
export * from './upload-modal-store'
export * from './load-image'
export * from './player'
export * from './get-song-by-id'
export * from './get-song-by-id'
export * from './load-song'
export * from './on-play'
14 changes: 14 additions & 0 deletions src/hooks/load-song/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Song } from '@models'
import { useSessionContext } from '@supabase/auth-helpers-react'

export function useLoadSongUrl(song: Song) {
const { supabaseClient } = useSessionContext()

if (!song || !supabaseClient || !song.song_path) return ''

const { data } = supabaseClient.storage
.from('songs')
.getPublicUrl(song.song_path)

return data.publicUrl
}
13 changes: 13 additions & 0 deletions src/hooks/on-play/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Song } from '@models'
import { usePlayerStore } from '@hooks'

export function useOnPlay(songs: Song[]) {
const player = usePlayerStore()

function onPlay(id: string) {
player.setId(id)
player.setIds(songs.map((song) => song.id))
}

return onPlay
}

0 comments on commit 329411a

Please sign in to comment.