MUSICAPP/.DS_Store
MUSICAPP/.gitattributes
# Auto detect text files and perform LF normalization
* text=auto
MUSICAPP/.gitignore
node_modules
MUSICAPP/actions/index.js
import axios from 'axios';
import _ from 'lodash';
import { AsyncStorage } from 'react-native';
const API_KEY = '05800d55eamsh896e3311b03f357p1acc36jsn2f43f188326e';
const axiosInstance = axios.create({
aseURL: 'https:
deezerdevs-deezer.p.rapidapi.com/',
timeout: 2000,
headers: {'x-rapidapi-key':API_KEY}
});
export const searchTracks = singerName => {
return axiosInstance.get(`search?q=${singerName}`).then(
response => {
const album = response.data.data.map((item) => item.album);
const uniqueAlbum = _.uniqBy(album, 'title');
return uniqueAlbum;
})
}
export const getAlbumTracks = albumId =
{
return axiosInstance.get(`album/${albumId}`).then(response => response.data.tracks.data)
}
export const storeData = async (key, value) => {
const stringifyValue = JSON.stringify(value);
try {
await AsyncStorage.setItem(key, stringifyValue);
return value;
} catch (e
or) {
E
or saving data
}
}
export const retrieveData = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
} catch (e
or) {
E
or retrieving data
}
}
export const clearStorage = async () => {
try {
await AsyncStorage.clear();
return true;
} catch (e
or) {
E
or saving data
}
}
MUSICAPP/App.js
import { AppLoading } from "expo";
import { Asset } from "expo-asset";
import * as Font from "expo-font";
import React, { useState } from "react";
import { Platform, StatusBar, StyleSheet, View } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import AppNavigator from "./navigation/AppNavigator";
import { Provider } from "react-redux";
import { store } from "./src/_helpers";
import { Login } from "./src/Login";
setup fake backend
import { configureFakeBackend } from "./src/_helpers";
configureFakeBackend();
export default function App(props) {
const [isLoadingComplete, setLoadingComplete] = useState(false);
const user = JSON.parse(localStorage.getItem("user")) || [];
if (!isLoadingComplete && !props.skipLoadingScreen) {
return (
startAsync={loadResourcesAsync}
onE
or={handleLoadingE
or}
onFinish={() => handleFinishLoading(setLoadingComplete)}
);
} else if (user.token) {
return (
{Platform.OS === "ios" &&
}
View
);
} else {
return (
Provide
);
}
}
async function loadResourcesAsync() {
await Promise.all([
Asset.loadAsync([
require("./assets/images
obot-dev.png"),
require("./assets/images
obot-prod.png"),
]),
Font.loadAsync({
This is the font that we are using for our tab ba
...Ionicons.font,
We include SpaceMono because we use it in HomeScreen.js. Feel free to
remove this if you are not using it in your app
"space-mono": require("./assets/fonts/SpaceMono-Regular.ttf"),
}),
]);
}
function handleLoadingE
or(e
or) {
In this case, you might want to report the e
or to your e
or reporting
service, for example Sentry
console.warn(e
or);
}
function handleFinishLoading(setLoadingComplete) {
setLoadingComplete(true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#eef2ed",
},
});
MUSICAPP/app.json
{
"expo": {
"name": "Music App",
"slug": "my-music-app",
"privacy": "public",
"platforms": [
"ios",
"android",
"web"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"splash": {
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#FFFFFF"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}
MUSICAPP/assets/fonts/SpaceMono-Regular.ttf
MUSICAPP/assets/images/icon.PNG
MUSICAPP/assets/images
obot-dev.png
MUSICAPP/assets/images
obot-prod.png
MUSICAPP/assets/images/splash.png
MUSICAPP
abel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
MUSICAPP/components/__tests__/__snapshots__/StyledText-test.js.snap
Jest Snapshot v1, https:
goo.gl/fbAQLP
exports[`renders co
ectly 1`] = `
Text
style={
A
ay [
undefined,
Object {
"fontFamily": "space-mono",
},
]
}
Snapshot test!
Text
`;
MUSICAPP/components/__tests__/StyledText-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import { MonoText } from '../StyledText';
it(`renders co
ectly`, () => {
const tree = renderer.create(
Snapshot test!
MonoText>).toJSON();
expect(tree).toMatchSnapshot();
});
MUSICAPP/components/CardList.js
import React from 'react';
import {View} from 'react-native';
import {Card, Button, Text } from 'react-native-elements';
export class CardList extends React.Component
{
renderData() {
const {data,imageKey,titleKey,buttonText, bottomView} = this.props;
return data.map ((item, index) =
{
return (
key={index}
title={item[titleKey]}
image={{uri: item[imageKey]}}
{bottomView(item)}
Card
)
})
}
render()
{
const {data} = this.props;
if(data && data.length > 0)
{
return this.renderData();
}
else{
return Text>Loading Data...
Text
View
}
}
}
MUSICAPP/components/SearchList.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
import {Label, TextInput, Button, Input } from 'react-native-elements';
import { SearchBar } from 'react-native-elements';
export class SearchList extends React.Component {
constructor()
{
super();
this.state = {
value: ''
}
}
componentDidMount() {
this.input.focus();
}
onChange(value) {
this.setState({value});
}
onSubmitSearch()
{
const { submitSearch } = this.props;
console.log(this.state.value);
submitSearch(this.state.value);
}
render() {
return (
this.input = input} placeholder="Search Artist" onChangeText={(event) => {this.onChange(event)}}