SpotifyClone
SpotifyClone copied to clipboard
how to make the user play all the song in the album when they click the pause button in Album Screen
Hi dear hoping you help me on this one and also a big thank you for turning in to my question I am working on a musical app I am using react-native and aws has my backend tools my problem is I have a album and I will like to play the whole album I mean all the song in the album if the user hit the album play button , below is my code for the db schema and the album button and the player Widget ...
Here is the code for the albumHeader
import React from 'react';
import { View, Text, Image } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { Album } from '../../types';
import styles from './styles';
export type AlbumHeaderProp = {
album: Album;
}
const AlbumHeader = (props: AlbumHeaderProp) => {
const { album } = props;
return (
<View style={styles.container}>
<Image source={{ uri: album.imageUri }} style={styles.image} />
<Text style={styles.name}>{album.name}</Text>
<View style={styles.creatorContainer}>
<Text style={styles.creator}>By {album.by}</Text>
<Text style={styles.likes}>{album.numberOfLikes} Likes</Text>
</View>
// This area is the play button I am talking about
<TouchableOpacity>
<View style={styles.button}>
<Text style={styles.buttonText}>Play</Text>
</View>
</TouchableOpacity>
</View>
)
}
export default AlbumHeader;
Here is the SongListIem file
import React, { useContext } from 'react';
import { Text, Image, View, TouchableWithoutFeedback, TouchableOpacity } from 'react-native';
import styles from './styles';
import { Song } from "../../types";
import { AppContext } from '../../AppContext';
export type SongListItemProps = {
song: Song
}
const SongListItem = (props: SongListItemProps) => {
const { song } = props;
const { setSongId, songId } = useContext(AppContext);
const onPlay = () => {
setSongId(song.id);
}
return (
<TouchableOpacity onPress={onPlay}>
<View style={styles.container}>
<Image source={{ uri: song.imageUri }} style={styles.image} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{song.title}</Text>
<Text style={styles.artist}>{song.artist}</Text>
</View>
</View>
</TouchableOpacity>
)
}
export default SongListItem;
Here is the player Widget
import React, { useContext, useEffect, useState } from 'react';
import { Text, Image, View, TouchableOpacity } from 'react-native';
import { AntDesign, FontAwesome } from "@expo/vector-icons";
import { API, graphqlOperation } from 'aws-amplify';
import styles from './styles';
import { Song } from "../../types";
import { Sound } from "expo-av/build/Audio/Sound";
import { AppContext } from '../../AppContext';
import { getSong } from "../../src/graphql/queries";
const PlayerWidget = () => {
const { songId } = useContext(AppContext);
const [song, setSong] = useState(null);
const [sound, setSound] = useState<Sound | null>(null);
const [isPlaying, setIsPlaying] = useState<boolean>(true);
const [duration, setDuration] = useState<number | null>(null);
const [position, setPosition] = useState<number | null>(null);
useEffect(() => {
const fetchSong = async () => {
try {
const data = await API.graphql(graphqlOperation(getSong, { id: songId }))
setSong(data.data.getSong);
} catch (e) {
console.log(e);
}
}
fetchSong();
}, [songId]);
if (song?.artist.length > 10) {
song.artist = song.artist.substring(0, 6) + "...";
}
if (song?.title.length > 8) {
song.title = song.title.substring(0, 5) + "...";
}
const onPlaybackStatusUpdate = (status) => {
setIsPlaying(status.isPlaying);
setDuration(status.durationMillis);
setPosition(status.positionMillis);
}
const playCurrentSong = async () => {
if (sound) {
await sound.unloadAsync();
}
const { sound: newSound } = await Sound.createAsync(
{ uri: song.uri },
{ shouldPlay: isPlaying },
onPlaybackStatusUpdate
)
setSound(newSound)
}
useEffect(() => {
if (song) {
playCurrentSong();
}
}, [song])
const onPlayPausePress = async () => {
if (!sound) {
return;
}
if (isPlaying) {
await sound.pauseAsync();
}
else {
await sound.playAsync();
}
}
const getProgress = () => {
if (sound === null || duration === null || position === null) {
return 0;
}
return (position / duration) * 100;
}
if (!song) {
return null;
}
return (
<View style={styles.container}>
<View style={[styles.progress, { width: `${getProgress()}%` }]} />
<View style={styles.row}>
<Image source={{ uri: song.imageUri }} style={styles.image} />
<View style={styles.rightContainer}>
<View style={styles.nameContainer}>
<Text style={styles.title}>{song.title}</Text>
<Text style={styles.artist}>{song.artist}</Text>
</View>
<View style={styles.iconsContainer}>
<AntDesign name="hearto" size={30} color={"white"} />
<TouchableOpacity onPress={onPlayPausePress}>
<FontAwesome name={isPlaying ? 'pause' : 'play'} size={30} color={"white"} />
</TouchableOpacity>
</View>
</View>
</View>
</View>
)
}
export default PlayerWidget;
Here is the AppContext
import React from 'react';
const context = {
songId: null,
setSongId: (id: string) => {
}
}
export const AppContext = React.createContext(context);
This one is a bit boring but if you need the Schema here is it
/* tslint:disable */
/* eslint-disable */
// this is an auto generated file. This will be overwritten
export const getAlbumCategory = /* GraphQL */ `
query GetAlbumCategory($id: ID!) {
getAlbumCategory(id: $id) {
id
title
albums {
items {
id
name
by
numberOfLikes
imageUri
artistsHeadline
albumCategoryId
createdAt
updatedAt
}
nextToken
}
createdAt
updatedAt
}
}
`;
export const listAlbumCategorys = /* GraphQL */ `
query ListAlbumCategorys(
$filter: ModelAlbumCategoryFilterInput
$limit: Int
$nextToken: String
) {
listAlbumCategorys(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
title
albums {
items{
id
imageUri
artistsHeadline
}
}
createdAt
updatedAt
}
nextToken
}
}
`;
export const getAlbum = /* GraphQL */ `
query GetAlbum($id: ID!) {
getAlbum(id: $id) {
id
name
by
numberOfLikes
imageUri
artistsHeadline
songs {
items {
id
imageUri
uri
title
artist
albumId
createdAt
updatedAt
}
nextToken
}
albumCategoryId
albumCategory {
id
title
albums {
nextToken
}
createdAt
updatedAt
}
createdAt
updatedAt
}
}
`;
export const listAlbums = /* GraphQL */ `
query ListAlbums(
$filter: ModelAlbumFilterInput
$limit: Int
$nextToken: String
) {
listAlbums(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
name
by
numberOfLikes
imageUri
artistsHeadline
songs {
nextToken
}
albumCategoryId
albumCategory {
id
title
createdAt
updatedAt
}
createdAt
updatedAt
}
nextToken
}
}
`;
export const getSong = /* GraphQL */ `
query GetSong($id: ID!) {
getSong(id: $id) {
id
imageUri
uri
title
artist
albumId
album {
id
name
by
numberOfLikes
imageUri
artistsHeadline
songs {
nextToken
}
albumCategoryId
albumCategory {
id
title
createdAt
updatedAt
}
createdAt
updatedAt
}
createdAt
updatedAt
}
}
`;
export const listSongs = /* GraphQL */ `
query ListSongs(
$filter: ModelSongFilterInput
$limit: Int
$nextToken: String
) {
listSongs(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
imageUri
uri
title
artist
albumId
album {
id
name
by
numberOfLikes
imageUri
artistsHeadline
albumCategoryId
createdAt
updatedAt
}
createdAt
updatedAt
}
nextToken
}
}
`;
Working on a similar thing, will probably put up a PR soon