Skip to content
This repository was archived by the owner on Jun 28, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/containers/Surah/connect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { isAllLoaded, loadAll, setCurrent as setCurrentSurah } from '../../redux/modules/surahs';
import { clearCurrent, isLoaded, load as loadAyahs } from '../../redux/modules/ayahs';

import debug from 'helpers/debug';

export const surahsConnect = ({ store: { getState, dispatch } }) => {
debug('component:Surah:surahsConnect', 'Init');

if (!isAllLoaded(getState())) {
debug('component:Surah:surahsConnect', 'Surahs not loaded');

return dispatch(loadAll());
}

return true;
}

export const ayahsConnect = ({ store: { dispatch, getState }, params }) => {
debug('component:Surah:ayahsConnect', 'Init');

const range = params.range;
const surahId = parseInt(params.surahId, 10);

let from;
let to;

if (range) {
if (range.includes('-')) {
[from, to] = range.split('-');
} else {
// Single ayah. For example /2/30
from = range;
to = parseInt(range, 10) + ayahRangeSize;
}

if (isNaN(from) || isNaN(to)) {
// Something wrong happened like /2/SOMETHING
// going to rescue by giving beginning of surah.
[from, to] = [1, ayahRangeSize];
}
} else {
[from, to] = [1, ayahRangeSize];
}

from = parseInt(from, 10);
to = parseInt(to, 10);

if (surahId !== getState().surahs.current) {
dispatch(setCurrentSurah(surahId));
}

if (!isLoaded(getState(), surahId, from, to)) {
debug('component:Surah:ayahsConnect', 'Not loaded');

dispatch(clearCurrent(surahId)); // In the case where you go to same surah but later ayahs.

return dispatch(loadAyahs(surahId, from, to, getState().options));
}

return true;
}
155 changes: 50 additions & 105 deletions src/containers/Surah/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,73 +36,19 @@ import descriptions from './descriptions';

const style = require('./style.scss');

import { clearCurrent, isLoaded, load as loadAyahs, setCurrentAyah, setCurrentWord, clearCurrentWord } from '../../redux/modules/ayahs';
import { isAllLoaded, loadAll, setCurrent as setCurrentSurah } from '../../redux/modules/surahs';
import { surahsConnect, ayahsConnect } from './connect';
import { load as loadAyahs, setCurrentAyah, setCurrentWord, clearCurrentWord } from '../../redux/modules/ayahs';
import { setOption, toggleReadingMode } from '../../redux/modules/options';

let lastScroll = 0;
const ayahRangeSize = 30;

@asyncConnect([
{
promise({ store: { getState, dispatch } }) {
debug('component:Surah', 'All Surahs Promise');
if (!isAllLoaded(getState())) {
debug('component:Surah', 'All Surahs Promise, Surahs not loaded');
return dispatch(loadAll());
}

return true;
}
promise: surahsConnect
},
{
promise({ store: { dispatch, getState }, params }) {
debug('component:Surah', 'Ayahs Promise');
const range = params.range;
const surahId = parseInt(params.surahId, 10);
const { options } = getState();
let from;
let to;

if (range) {
if (range.includes('-')) {
[from, to] = range.split('-');
} else {
// Single ayah. For example /2/30
from = range;
to = parseInt(range, 10) + ayahRangeSize;
}

if (isNaN(from) || isNaN(to)) {
// Something wrong happened like /2/SOMETHING
// going to rescue by giving beginning of surah.
[from, to] = [1, ayahRangeSize];
}
} else {
[from, to] = [1, ayahRangeSize];
}

if (isNaN(surahId)) {
// Should have an alert or something to tell user there is an error.
return dispatch(push('/'));
}

from = parseInt(from, 10);
to = parseInt(to, 10);

if (surahId !== getState().surahs.current) {
dispatch(setCurrentSurah(surahId));
}

if (!isLoaded(getState(), surahId, from, to)) {
debug('component:Surah', 'Ayahs Promise, Ayahs not loaded');
dispatch(clearCurrent(surahId)); // In the case where you go to same surah but later ayahs.

return dispatch(loadAyahs(surahId, from, to, options));
}

return true;
}
promise: ayahsConnect
}
])
@connect(
Expand Down Expand Up @@ -135,12 +81,12 @@ const ayahRangeSize = 30;
};
},
{
loadAyahsDispatch: loadAyahs,
setOptionDispatch: setOption,
toggleReadingModeDispatch: toggleReadingMode,
setCurrentAyah: setCurrentAyah,
setCurrentWord: setCurrentWord,
clearCurrentWord: clearCurrentWord,
loadAyahs,
setOption,
toggleReadingMode,
setCurrentAyah,
setCurrentWord,
clearCurrentWord,
push
}
)
Expand All @@ -160,23 +106,23 @@ export default class Surah extends Component {

return conditions.some(condition => condition);
}
// If shouldComponentUpdate returns false, then __render() will be completely skipped__ until the next state change.
// In addition, __componentWillUpdate and componentDidUpdate will not be called__.

constructor() {
super(...arguments);
}

state = {
lazyLoading: false
};

componentWillMount() {
const {params, surah, push } = this.props;
let start = parseInt(params.range.split('-')[0], 10);
const { params, surah, push } = this.props;

if (params.range && params.range.includes('-')) {
const start = parseInt(params.range.split('-')[0], 10);

if(start > surah.ayat || isNaN(start)){
return push('/error/invalid-ayah-range');
}
}
}

componentDidMount() {
if (__CLIENT__) {
window.removeEventListener('scroll', this.handleNavbar, true);
Expand Down Expand Up @@ -231,24 +177,24 @@ export default class Surah extends Component {
}

handleOptionChange(payload) {
const { setOptionDispatch, loadAyahsDispatch, surah, ayahIds, options } = this.props;
const { setOption, loadAyahs, surah, ayahIds, options } = this.props;
const from = ayahIds.first();
const to = ayahIds.last();

setOptionDispatch(payload);
loadAyahsDispatch(surah.id, from, to, Object.assign({}, options, payload));
setOption(payload);
loadAyahs(surah.id, from, to, Object.assign({}, options, payload));
}

handleFontSizeChange = (payload) => {
const { setOptionDispatch } = this.props;
const { setOption } = this.props;

return setOptionDispatch(payload);
return setOption(payload);
}

handleSurahInfoToggle = (payload) => {
const { setOptionDispatch } = this.props;
const { setOption } = this.props;

return setOptionDispatch(payload);
return setOption(payload);
}

handleNavbar = () => {
Expand Down Expand Up @@ -276,14 +222,29 @@ export default class Surah extends Component {
return push(`/${surah.id}/${ayahNum}-${ayahNum + 10}`);
}

this.lazyLoadAyahs(() => setTimeout(() => {
this.handleLazyLoadAyahs(() => setTimeout(() => {
scroller.scrollTo('ayah:'+ ayahNum);
}, 1000)); // then scroll to it
}

handleWordClick(id) {
const { setCurrentWord, clearCurrentWord, currentWord, isStarted } = this.props;
if (id == currentWord && !isStarted) {
clearCurrentWord();
} else {
setCurrentWord(id);
}
}

lazyLoadAyahs(callback) {
const { loadAyahsDispatch, ayahIds, surah, isEndOfSurah, options } = this.props;
handleWordFocus(id, elem) {
const { setCurrentWord, clearCurrentWord, currentWord, isStarted } = this.props;
if (id != currentWord && isStarted) {
setCurrentWord(id); // let tabbing around while playing trigger seek to word action
}
}

handleLazyLoadAyahs(callback) {
const { loadAyahs, ayahIds, surah, isEndOfSurah, options } = this.props;

const range = [ayahIds.first(), ayahIds.last()];
let size = 10;
Expand All @@ -296,7 +257,7 @@ export default class Surah extends Component {
const to = (from + size);

if (!isEndOfSurah && !ayahIds.has(to)) {
loadAyahsDispatch(surah.id, from, to, options).then(() => {
loadAyahs(surah.id, from, to, options).then(() => {
this.setState({lazyLoading: false});
if (callback) {
callback();
Expand All @@ -310,7 +271,7 @@ export default class Surah extends Component {

return (
<LazyLoad
onLazyLoad={this.lazyLoadAyahs.bind(this)}
onLazyLoad={this.handleLazyLoadAyahs.bind(this)}
isEnd={isEndOfSurah && !isLoading}
isLoading={isLoading}
endComponent={
Expand Down Expand Up @@ -343,31 +304,15 @@ export default class Surah extends Component {
);
}

onWordClick(id) {
const { setCurrentWord, clearCurrentWord, currentWord, isStarted } = this.props;
if (id == currentWord && !isStarted) {
clearCurrentWord();
} else {
setCurrentWord(id);
}
}

onWordFocus(id, elem) {
const { setCurrentWord, clearCurrentWord, currentWord, isStarted } = this.props;
if (id != currentWord && isStarted) {
setCurrentWord(id); // let tabbing around while playing trigger seek to word action
}
}

renderAyahs() {
const { ayahs, currentWord } = this.props;

return Object.values(ayahs).map(ayah => (
<Ayah
ayah={ayah}
currentWord={currentWord && (new RegExp('^'+ ayah.ayahKey +':')).test(currentWord)? parseInt(currentWord.match(/\d+$/)[0], 10) : null}
onWordClick={this.onWordClick.bind(this)}
onWordFocus={this.onWordFocus.bind(this)}
onWordClick={this.handleWordClick.bind(this)}
onWordFocus={this.handleWordFocus.bind(this)}
key={`${ayah.surahId}-${ayah.ayahNum}-ayah`}
/>
));
Expand All @@ -394,7 +339,7 @@ export default class Surah extends Component {
}

renderTopOptions() {
const { toggleReadingModeDispatch, options } = this.props;
const { toggleReadingMode, options } = this.props;

return (
<Row>
Expand All @@ -417,7 +362,7 @@ export default class Surah extends Component {
<li>
<ReadingModeToggle
isToggled={options.isReadingMode}
onReadingModeToggle={toggleReadingModeDispatch} />
onReadingModeToggle={toggleReadingMode} />
</li>
</ul>
</Col>
Expand Down Expand Up @@ -484,7 +429,7 @@ export default class Surah extends Component {
/>
<Audioplayer
surah={surah}
onLoadAyahs={this.lazyLoadAyahs.bind(this)}
onLoadAyahs={this.handleLazyLoadAyahs.bind(this)}
className={`col-md-4 ${style.rightborder}`}
/>
<ContentDropdown
Expand Down