-
Notifications
You must be signed in to change notification settings - Fork 75
Open
Description
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
}
}
`;
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels