diff --git a/api/tasks/addAudioData.js b/api/tasks/addAudioData.js index 5d3706e..c2401eb 100644 --- a/api/tasks/addAudioData.js +++ b/api/tasks/addAudioData.js @@ -6,8 +6,7 @@ const createData = (files, index) => { if (file.qari && (!file.format || !file.metadata)) { const url = `http://download.quranicaudio.com/quran/${file.qari.relative_path}${file.file_name}`; - console.log(url); - try{ + try { return probe(url, (err, data) => { file.metadata = data.metadata; file.format = data.format; @@ -15,11 +14,11 @@ const createData = (files, index) => { createData(files, index + 1); }); - } catch(error) { + } catch (error) { console.warn(error); } } -} +}; models.audioFile.all({ where: {extension: 'mp3', metadata: null, format: null}, include: [models.qari] }).then(files => { return createData(files, 0); diff --git a/src/actions/audioplayer.js b/src/actions/audioplayer.js index 9e5b931..5f00ca3 100644 --- a/src/actions/audioplayer.js +++ b/src/actions/audioplayer.js @@ -62,11 +62,13 @@ export function random() { }; } -export function load({ surah, qari }) { +export function load({ surah, qari, surahPage, qaris }) { return { type: LOAD, surah, - qari + qari, + surahPage, + qaris }; } diff --git a/src/components/Audioplayer/index.js b/src/components/Audioplayer/index.js index 4bb34d7..fa0029b 100644 --- a/src/components/Audioplayer/index.js +++ b/src/components/Audioplayer/index.js @@ -24,26 +24,11 @@ import Track from './Track'; const styles = require('./style.scss'); -@connect( - state => ({ - file: state.audioplayer.file, - surahs: state.surahs.entities, - qari: state.audioplayer.qari, - surah: state.audioplayer.surah, - progress: state.audioplayer.progress, - duration: state.audioplayer.duration, - currentTime: state.audioplayer.currentTime, - isPlaying: state.audioplayer.isPlaying, - shouldRepeat: state.audioplayer.shouldRepeat, - shouldContinuous: state.audioplayer.shouldContinuous, - shouldRandom: state.audioplayer.shouldRandom, - }), - { load, play, pause, playPause, update, repeat, next, previous, continuous, random } -) -export default class Audioplayer extends Component { +class Audioplayer extends Component { static propTypes = { load: PropTypes.func.isRequired, surahs: PropTypes.object.isRequired, + qaris: PropTypes.object, surah: PropTypes.shape({ id: PropTypes.number.isRequired, ayat: PropTypes.number.isRequired, @@ -65,13 +50,14 @@ export default class Audioplayer extends Component { shouldRepeat: PropTypes.bool.isRequired, shouldContinuous: PropTypes.bool.isRequired, shouldRandom: PropTypes.bool.isRequired, + surahPage: PropTypes.bool, progress: PropTypes.number, currentTime: PropTypes.number, duration: PropTypes.number }; componentWillReceiveProps(nextProps) { - if (this.props.surah !== nextProps.surah) { + if (this.props.surah !== nextProps.surah || this.props.qari !== nextProps.qari) { this.handleFileLoad(nextProps.file); this.handleRemoveFileListeneres(this.props.file); } @@ -178,8 +164,9 @@ export default class Audioplayer extends Component { } renderPreviousButton() { - const { previous, surah, surahs } = this.props; // eslint-disable-line no-shadow - const disabled = surah ? surah.id === 1 && true : true; + const { previous, surah, surahs, surahPage, qari } = this.props; // eslint-disable-line no-shadow + const disableBasedOnSurah = surah ? surah.id === 1 && true : true; + const disabled = surahPage ? qari.id === 1 && true : disableBasedOnSurah; return ( ({ + file: state.audioplayer.file, + surahs: state.surahs.entities, + qari: state.audioplayer.qari, + qaris: state.audioplayer.qaris, + surah: state.audioplayer.surah, + progress: state.audioplayer.progress, + duration: state.audioplayer.duration, + currentTime: state.audioplayer.currentTime, + isPlaying: state.audioplayer.isPlaying, + shouldRepeat: state.audioplayer.shouldRepeat, + surahPage: state.audioplayer.surahPage, + shouldContinuous: state.audioplayer.shouldContinuous, + shouldRandom: state.audioplayer.shouldRandom, + }), + { load, play, pause, playPause, update, repeat, next, previous, continuous, random } +)(Audioplayer); diff --git a/src/components/Header/index.js b/src/components/Header/index.js new file mode 100644 index 0000000..939e8eb --- /dev/null +++ b/src/components/Header/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import Grid from 'react-bootstrap/lib/Grid'; +import Row from 'react-bootstrap/lib/Row'; +import Col from 'react-bootstrap/lib/Col'; +const styles = require('./style.scss'); +export default () => ( + + + +

QuranicAudio

+ +
+
+); diff --git a/src/components/Header/style.scss b/src/components/Header/style.scss new file mode 100644 index 0000000..fc302ee --- /dev/null +++ b/src/components/Header/style.scss @@ -0,0 +1,41 @@ +@import "../../styles/variables.scss"; + +.header { + background-color: $brand-primary; + background: url('../../../static/images/index-bg.jpg') center center no-repeat; + background-size: cover; + height: 300px; + color: #fff; + + @include mobile() { + height: 30vh; + padding: 1px; + + &.fixed { + position: fixed; + top: 0px; + width:100%; + height: 120px; + background: #009faa; + color: #FFF; + font-size: 23px; + padding-top: 50px; + transition: height 0.3s linear 0s, padding 0.3s linear 0s; + overflow:hidden; + } + } +} + +.header__text { + @include mobile() { + margin-top: 15%; + } +} + +.heading { + font-family: 'Montserrat-Bold'; + font-size: 48px; + margin-top: 80px; + left: 0; + position: relative; +} diff --git a/src/containers/Main/about.js b/src/containers/Main/about.js index 19b3a35..28e0b16 100644 --- a/src/containers/Main/about.js +++ b/src/containers/Main/about.js @@ -1,49 +1,33 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; +import React from 'react'; import Grid from 'react-bootstrap/lib/Grid'; import Row from 'react-bootstrap/lib/Row'; import Col from 'react-bootstrap/lib/Col'; -import Link from 'react-router/lib/Link'; +import Header from '../../components/Header'; const styles = require('./style.scss'); -class Home extends Component { - render() { - return ( -
- - - -

QuranicAudio

- -
-
- - - - -

About

-

- QuranicAudio.com is the largest collection of cd quality Quran recitations on the internet. Mp3s on this site may be downloaded and used for personal use free of charge. However, you may not use these files for commercial purposes as many of these files have rules and regulations that prevent their sale except by the publishing companies. -

-

- QuranicAudio.com is the largest collection of cd quality Quran recitations on the internet. Mp3s on this site may be downloaded and used for personal use free of charge. However, you may not use these files for commercial purposes as many of these files have rules and regulations that prevent their sale except by the publishing companies. -

-

- Files on QuranicAudio.com come from many different sources. Many of them are hand ripped from cds. Others have been downloaded from various other high quality sites on the internet, including HidayahOnline, DawahAcademy, Kalamullah.com, Sabbir.com, dhikrullah.com, zanjabil.net, shuraym.com, and others. Many of the files have also been sent to us by some of our users, may Allah reward them greatly. -

-
- -
-
-
- ); - } -} - -export default connect( - state => ({ - qaris: state.qaris.entities, - sections: state.sections.entities - }) -)(Home); +export default () => { + return ( +
+
+ + + + +

About

+

+ QuranicAudio.com is the largest collection of cd quality Quran recitations on the internet. Mp3s on this site may be downloaded and used for personal use free of charge. However, you may not use these files for commercial purposes as many of these files have rules and regulations that prevent their sale except by the publishing companies. +

+

+ QuranicAudio.com is the largest collection of cd quality Quran recitations on the internet. Mp3s on this site may be downloaded and used for personal use free of charge. However, you may not use these files for commercial purposes as many of these files have rules and regulations that prevent their sale except by the publishing companies. +

+

+ Files on QuranicAudio.com come from many different sources. Many of them are hand ripped from cds. Others have been downloaded from various other high quality sites on the internet, including HidayahOnline, DawahAcademy, Kalamullah.com, Sabbir.com, dhikrullah.com, zanjabil.net, shuraym.com, and others. Many of the files have also been sent to us by some of our users, may Allah reward them greatly. +

+
+ +
+
+
+ ); +}; diff --git a/src/containers/Main/index.js b/src/containers/Main/index.js index 53e0ca2..81f4a4f 100644 --- a/src/containers/Main/index.js +++ b/src/containers/Main/index.js @@ -7,6 +7,7 @@ import Nav from 'react-bootstrap/lib/Nav'; import NavItem from 'react-bootstrap/lib/NavItem'; import formatQarisByLetter from '../../utils/formatQarisByLetter'; import QarisList from '../../components/QarisList'; +import Header from '../../components/Header'; const styles = require('./style.scss'); @@ -51,11 +52,7 @@ class Home extends Component { return (
- - -

QuranicAudio

- -
+
diff --git a/src/containers/Qari/Sura.js b/src/containers/Qari/Sura.js new file mode 100644 index 0000000..1f8d5da --- /dev/null +++ b/src/containers/Qari/Sura.js @@ -0,0 +1,136 @@ +import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { asyncConnect } from 'redux-connect'; +import Grid from 'react-bootstrap/lib/Grid'; +import Row from 'react-bootstrap/lib/Row'; +import Col from 'react-bootstrap/lib/Col'; +import Helmet from 'react-helmet'; +import { load, play, next} from 'actions/audioplayer'; +import { load as loadFiles } from 'actions/files'; +import Button from 'react-bootstrap/lib/Button'; +import zeroPad from 'utils/zeroPad'; +import Link from 'react-router/lib/Link'; + +const styles = require('./style.scss'); + +class Sura extends Component { + + static propTypes = { + surahs: PropTypes.object.isRequired, + surah: PropTypes.object.isRequired, + currentQari: PropTypes.object.isRequired, + state: PropTypes.object.isRequired, + files: PropTypes.object.isRequired, + load: PropTypes.func.isRequired, + play: PropTypes.func.isRequired, + params: PropTypes.any, + next: PropTypes.func.isRequired, + Playing: PropTypes.bool.isRequired, + qaris: PropTypes.object.isRequired + }; + + handleSurahSelection = (qari) => { + const { surah, qaris} = this.props; + + this.props.load({ qari, surah, surahPage: true, qaris}); + } + + render() { + const { surah, Playing, qaris, currentQari} = this.props; + return ( +
+ + + + +

+ Surat {`${surah.name.simple}`} +

+
+ +
+ +
+
+ + + +
+
    + { + Object.keys(qaris).map( (qariId) => { + const qari = qaris[qariId]; + return ( +
  • this.handleSurahSelection(qari)} + > + + + + +
    + + {qari.id}. + + +
    + + +
    event.stopPropagation()} to={`/quran/${qari.id}`}>{qari.name}
    + +
    + + + + +
    +
  • ); + }) + } +
+
+ +
+
+
+ ); + } +} + +const connectedSura = connect( + (state, ownProps) => ({ + surahs: state.surahs.entities, + surah: state.surahs.entities[Number(ownProps.params.id)], + qaris: state.qaris.entities, + files: state.files.entities, + Playing: state.audioplayer.isPlaying, + state: state, + currentQari: (state.audioplayer && state.audioplayer.qari) ? state.audioplayer.qari : {}, + }), + { load, play, next} +)(Sura); + +export default asyncConnect([{ + promise({ params, store: { dispatch } }) { + return dispatch(loadFiles(Number(params.id))); + } +}])(connectedSura); diff --git a/src/containers/Qari/index.js b/src/containers/Qari/index.js index b5ed926..8428c5e 100644 --- a/src/containers/Qari/index.js +++ b/src/containers/Qari/index.js @@ -10,6 +10,8 @@ import { load, play, next, continuous} from 'actions/audioplayer'; import { load as loadFiles } from 'actions/files'; import zeroPad from 'utils/zeroPad'; import formatSeconds from 'utils/formatSeconds'; +import Link from 'react-router/lib/Link'; + const styles = require('./style.scss'); class Qaris extends Component { @@ -93,9 +95,7 @@ class Qaris extends Component { -
- Surat {surah.name.simple} -
+
event.stopPropagation()} to={`/sura/${surah.id}`}>Surat {surah.name.simple}
diff --git a/src/containers/Qari/style.scss b/src/containers/Qari/style.scss index 9a7817e..b653ee5 100644 --- a/src/containers/Qari/style.scss +++ b/src/containers/Qari/style.scss @@ -160,3 +160,8 @@ width: inherit; } } + + +.link { + color: $grey; +} diff --git a/src/containers/index.js b/src/containers/index.js index 64e05d2..199b520 100644 --- a/src/containers/index.js +++ b/src/containers/index.js @@ -2,4 +2,5 @@ export App from './App'; export Home from './Main'; export NotFound from './NotFound'; export Qari from './Qari'; +export Sura from './Qari/Sura'; export About from './Main/about'; diff --git a/src/reducers/audioplayer.js b/src/reducers/audioplayer.js index 1a965a4..572abac 100644 --- a/src/reducers/audioplayer.js +++ b/src/reducers/audioplayer.js @@ -26,7 +26,9 @@ const initialState = { shouldContinuous: false, shouldRandom: false, progress: 0, - currentTime: 0 + currentTime: 0, + surahPage: false, + qaris: null }; export default function reducer(state = initialState, action = {}) { @@ -36,11 +38,18 @@ export default function reducer(state = initialState, action = {}) { const file = new Audio(`${AUDIO_URL}/${action.qari.relativePath}${zeroPad(action.surah.id, 3)}.mp3`); file.play(); + if (action.surahPage) { + state.qaris = action.qaris; + state.qari = action.qair; + } + + file.title = `${action.surah.name.simple} - ${action.qari.name}`; return { ...state, isPlaying: true, qari: action.qari, surah: action.surah, + surahPage: action.surahPage, file }; } @@ -106,27 +115,63 @@ export default function reducer(state = initialState, action = {}) { }; case NEXT: { state.file.pause(); - const file = new Audio(`${AUDIO_URL}/${state.qari.relativePath}${zeroPad(state.surah.id + 1, 3)}.mp3`); + let file = null; + let newState = {}; + if (state.surahPage) { + const nextQari = state.qaris[state.qari.id + 1]; + file = new Audio(`${AUDIO_URL}/${nextQari.relativePath}${zeroPad(state.surah.id, 3)}.mp3`); + file.title = `${state.surah.name.simple} - ${nextQari.name}`; + file.play(); + newState = { + ...state, + isPlaying: true, + surah: state.surah, + qari: nextQari, + file + }; + } else { + file = new Audio(`${AUDIO_URL}/${state.qari.relativePath}${zeroPad(state.surah.id + 1, 3)}.mp3`); + file.title = `${state.surah.name.simple} - ${state.qari.name}`; + newState = { + ...state, + isPlaying: true, + surah: action.surahs[state.surah.id] || state.surah, + qari: action.qari || state.qari, + file + }; + } file.play(); - return { - ...state, - isPlaying: true, - surah: action.surahs[state.surah.id] || state.surah, - qari: action.qari || state.qari, - file - }; + return newState; } case PREVIOUS: { state.file.pause(); - const file = new Audio(`${AUDIO_URL}/${state.qari.relativePath}${zeroPad(state.surah.id - 1, 3)}.mp3`); + let newState = {}; + let file = null; + if (state.surahPage) { + const previusQari = state.qaris[state.qari.id - 1]; + file = new Audio(`${AUDIO_URL}/${previusQari.relativePath}${zeroPad(state.surah.id, 3)}.mp3`); + file.title = `${state.surah.name.simple} - ${previusQari.name}`; + newState = { + ...state, + isPlaying: true, + surah: state.surah, + qari: previusQari, + file + }; + } else { + file = new Audio(`${AUDIO_URL}/${state.qari.relativePath}${zeroPad(state.surah.id - 1, 3)}.mp3`); + file.title = `${state.surah.name.simple} - ${state.qari.name}`; + newState = { + ...state, + isPlaying: true, + surah: action.surahs[state.surah.id - 2] || state.surah, + qari: action.qari || state.qari, + file + }; + } + file.play(); - return { - ...state, - isPlaying: true, - surah: action.surahs[state.surah.id - 2] || state.surah, - qari: action.qari || state.qari, - file - }; + return newState; } default: return state; diff --git a/src/routes.js b/src/routes.js index fc68f5a..f66e478 100644 --- a/src/routes.js +++ b/src/routes.js @@ -7,9 +7,15 @@ import { NotFound, Qaris, Qari, - About + About, + Sura } from 'containers'; +function isValid(nextState, replaceState) { + if (isNaN(nextState.params.id) || nextState.params.id > 114 || nextState.params.id < 1) { + replaceState('/'); + } +} export default () => { return ( @@ -22,6 +28,9 @@ export default () => { + + + { /* Catch all route */ } diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 6a172b8..0a6b188 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -7,6 +7,7 @@ $brand-info: #5bc0de; $border-color: #F0F0F0; $text-color: #444; $hover-grey: #f7f7f7; +$grey: #777777; $font-size-base: 14px; $font-family-sans-serif: 'Montserrat', sans-serif; $font-family-regular: 'Montserrat-regular', sans-serif; @@ -16,4 +17,3 @@ $navbar-inverse-color: #fff; $navbar-inverse-link-color: #fff; @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap/variables"; @import 'mixins'; -