Skip to content
This repository was archived by the owner on Jun 28, 2021. It is now read-only.
Prev Previous commit
Next Next commit
on word click working!
  • Loading branch information
mmahalwy committed Jun 30, 2016
commit 2e624ed39ba2344558ddfda9b53e530f04a210d6
90 changes: 16 additions & 74 deletions src/components/Audioplayer/Segments/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { Component, PropTypes } from 'react';
import { decrypt } from 'sjcl';
import Helmet from 'react-helmet';

import debug from 'helpers/debug';

export default class Segments extends Component {
static propTypes = {
audio: PropTypes.object.isRequired,
segments: PropTypes.string.isRequired,
segments: PropTypes.object.isRequired,
currentAyah: PropTypes.string,
currentWord: PropTypes.string,
currentTime: PropTypes.number,
Expand All @@ -16,97 +17,38 @@ export default class Segments extends Component {
currentWord: null
};

state = {
intervals: [],
words: {},
};

// LIFECYCLE METHODS

componentDidMount() {
this.buildIntervals(this.props);
}

componentWillReceiveProps(nextProps) {
if (this.props.audio !== nextProps.audio) {
this.buildIntervals(nextProps);
}

if (this.props.currentTime !== nextProps.currentTime) {
if (this.state.words) {
let currentWord = null;

Object.keys(this.state.words).forEach(wordIndex => {
const word = this.state.words[wordIndex];

if (nextProps.currentTime > word.startTime && nextProps.currentTime < word.endTime) {
currentWord = `${nextProps.currentAyah}:${wordIndex}`;
}
});

this.props.onSetCurrentWord(currentWord);
}
}
}

shouldComponentUpdate(nextProps) {
return [
this.props.audio !== nextProps.audio,
this.props.currentAyah !== nextProps.currentAyah,
this.props.currentWord !== nextProps.currentWord,
this.props.currentTime !== nextProps.currentTime,
].some(test => test);
}

buildIntervals(props) {
const { segments } = props;

let parsedSegments = null;
try {
parsedSegments = JSON.parse(
decrypt(
process.env.SEGMENTS_KEY,
new Buffer(segments, 'base64').toString()
)
);
} catch (e) {
parsedSegments = [];
}
render() {
const { segments, currentAyah, currentTime } = this.props;
const style = [];
let currentWord = null;

const words = {};
const intervals = parsedSegments.map(segment => {
const startTime = segment[0];
const endTime = segment[0] + segment[1];
const duration = segment[1];
const wordIndex = segment[2];
const mappedVal = {
startTime: startTime / 1000,
endTime: endTime / 1000,
duration: duration / 1000
};
Object.keys(segments.words).forEach(wordIndex => {
const word = segments.words[wordIndex];

if (wordIndex >= 0 && !words[wordIndex]) {
words[wordIndex] = mappedVal;
if (currentTime >= word.startTime && currentTime < word.endTime) {
currentWord = `${currentAyah}:${wordIndex}`;
}

return [startTime / 1000, endTime / 1000, wordIndex];
});

this.setState({ intervals, words });

return { intervals, words }; // for console debugging
}

render() {
const { currentWord } = this.props;
const style = [];

if (currentWord) {
debug('component:Segments', `render with currentWord ${currentWord}`);

style.push({
cssText: `#word-${currentWord.replace(/:/g, '-')}{
color: #279197;
border-color: #279197;
}`
});
} else {
debug('component:Segments', 'render without currentWord');
}

return (
Expand Down
40 changes: 20 additions & 20 deletions src/components/Audioplayer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const style = require('./style.scss');
isLoading: state.audioplayer.isLoading,
shouldRepeat: state.audioplayer.shouldRepeat,
shouldScroll: state.audioplayer.shouldScroll,
progress: state.audioplayer.progress,
duration: state.audioplayer.duration,
currentTime: state.audioplayer.currentTime,
}),
Expand Down Expand Up @@ -84,7 +83,6 @@ export default class Audioplayer extends Component {
toggleRepeat: PropTypes.func.isRequired,
toggleScroll: PropTypes.func.isRequired,
isPlaying: PropTypes.bool,
progress: PropTypes.number,
currentTime: PropTypes.number,
duration: PropTypes.number,
currentFile: PropTypes.object
Expand Down Expand Up @@ -233,32 +231,28 @@ export default class Audioplayer extends Component {
}

handleAddFileListeners(file) {
const { update } = this.props; // eslint-disable-line no-shadow
const { update, currentTime } = this.props; // eslint-disable-line no-shadow
debug('component:Audioplayer', `Attaching listeners to ${file.src}`);
// Preload file
file.setAttribute('preload', 'auto');

const onLoadeddata = () => {
// Default current time to zero. This will change
file.currentTime = 0; // eslint-disable-line no-param-reassign
file.currentTime = ( // eslint-disable-line no-param-reassign
file.currentTime ||
currentTime ||
0
);

return update({
duration: file.duration,
isLoading: false
});
};

const onTimeupdate = () => {
const progress = (
file.currentTime /
file.duration * 100
);

return update({
progress,
currentTime: file.currentTime
});
};
const onTimeupdate = () => update({
currentTime: file.currentTime
});

const onEnded = () => {
const { shouldRepeat } = this.props;
Expand All @@ -276,10 +270,16 @@ export default class Audioplayer extends Component {
return this.handleAyahChange();
};

const onPlay = () => {};
const onPlay = () => {
file.ontimeupdate = onTimeupdate; // eslint-disable-line no-param-reassign
};

const onPause = () => {
file.ontimeupdate = null; // eslint-disable-line no-param-reassign
};

file.onloadeddata = onLoadeddata; // eslint-disable-line no-param-reassign
file.ontimeupdate = onTimeupdate; // eslint-disable-line no-param-reassign
file.onpause = onPause; // eslint-disable-line no-param-reassign
file.onplay = onPlay; // eslint-disable-line no-param-reassign
file.onended = onEnded; // eslint-disable-line no-param-reassign

Expand All @@ -292,14 +292,14 @@ export default class Audioplayer extends Component {
file.onloadeddata = null; // eslint-disable-line no-param-reassign
file.ontimeupdate = null; // eslint-disable-line no-param-reassign
file.onplay = null; // eslint-disable-line no-param-reassign
file.onPause = null; // eslint-disable-line no-param-reassign
file.onended = null; // eslint-disable-line no-param-reassign
}

handleTrackChange = (fraction) => {
const { currentFile, update } = this.props; // eslint-disable-line no-shadow

update({
progress: fraction * 100,
currentTime: fraction * currentFile.duration
});

Expand Down Expand Up @@ -361,10 +361,10 @@ export default class Audioplayer extends Component {
currentAyah,
currentWord,
currentTime,
duration,
setCurrentWord, // eslint-disable-line no-shadow
isSupported,
isLoadedOnClient,
progress,
shouldRepeat, // eslint-disable-line no-shadow
shouldScroll, // eslint-disable-line no-shadow
toggleRepeat // eslint-disable-line no-shadow
Expand Down Expand Up @@ -411,7 +411,7 @@ export default class Audioplayer extends Component {
<div className={style.wrapper}>
{isLoadedOnClient ?
<Track
progress={progress}
progress={currentTime / duration * 100}
onTrackChange={this.handleTrackChange}
/> : null}
{isLoadedOnClient && segments[currentAyah] ?
Expand Down
33 changes: 10 additions & 23 deletions src/components/Ayah/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ export default class Ayah extends Component {
match: PropTypes.array,
isSearch: PropTypes.bool,
currentWord: PropTypes.any, // gets passed in an integer, null by default
onWordFocus: PropTypes.func,
onWordClick: PropTypes.func
onWordClick: PropTypes.func.isRequired
};

static defaultProps = {
Expand All @@ -43,20 +42,6 @@ export default class Ayah extends Component {
return conditions.some(condition => condition);
}

handleWordClick = (event) => {
if (event.target && /^word-/.test(event.target.id)) {
// call onWordClick in Surah
this.props.onWordClick(event.target.id.match(/\d+/g).join(':'));
}
}

handleWordFocus = (event) => {
if (event.target && /^word-/.test(event.target.id)) {
// call onWordFocus in Surah
this.props.onWordFocus(event.target.id.match(/\d+/g).join(':'), event.target);
}
}

handlePlay() {
this.setState({
open: false
Expand Down Expand Up @@ -88,19 +73,21 @@ export default class Ayah extends Component {
}

renderText() {
const { ayah } = this.props;
const { ayah, onWordClick } = this.props;

if (!ayah.words[0].code) {
return false;
}

let position = 0;
// position is important as it will differentiate between words and symbols, see 2:25:13
let position = -1;
let text = ayah.words.map(word => {
let id = null;
const className = `${word.className} ${word.highlight && word.highlight}`;

if (word.charTypeId === CHAR_TYPE_WORD) {
id = `word-${word.ayahKey.replace(/:/, '-')}-${position++}`;
position = position + 1;
id = `word-${word.ayahKey.replace(/:/, '-')}-${position}`;
} else {
id = `${word.className}-${word.codeDec}`; // just don't include id
}
Expand All @@ -112,12 +99,11 @@ export default class Ayah extends Component {
<b
key={word.code}
id={id}
onClick={this.handleWordClick}
// onFocus={this.handleWordFocus}
onClick={(event) => onWordClick(event.target.dataset.key)}
data-key={`${word.ayahKey}:${position}`}
className={`${className} pointer`}
data-toggle="tooltip"
data-trigger="hover"
// tabIndex="1" <-- disable word focus
data-placement="top" title={tooltip}
dangerouslySetInnerHTML={{__html: word.code}}
/>
Expand All @@ -127,7 +113,8 @@ export default class Ayah extends Component {
return (
<b
id={id}
onClick={this.handleWordClick}
onClick={(event) => onWordClick(event.target.dataset.key)}
data-key={`${word.ayahKey}:${position}`}
className={`${className} pointer`}
key={word.code}
dangerouslySetInnerHTML={{__html: word.code}}
Expand Down
35 changes: 3 additions & 32 deletions src/containers/Surah/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import { surahsConnect, ayahsConnect } from './connect';
import {
load as loadAyahs,
setCurrentAyah,
setCurrentWord,
clearCurrentWord
} from '../../redux/modules/ayahs';
import { setCurrentWord } from '../../redux/modules/audioplayer';

import { setOption, toggleReadingMode } from '../../redux/modules/options';

Expand Down Expand Up @@ -163,34 +163,6 @@ export default class Surah extends Component {
return false;
}

onWordClick = (id) => {
const {
setCurrentWord, // eslint-disable-line no-shadow
clearCurrentWord, // eslint-disable-line no-shadow
currentWord,
isStarted
} = this.props;

if (id === currentWord && !isStarted) {
clearCurrentWord();
} else {
setCurrentWord(id);
}
}

onWordFocus = (id) => {
const {
setCurrentWord, // eslint-disable-line no-shadow
currentWord,
isStarted
} = this.props;

if (id !== currentWord && isStarted) {
// let tabbing around while playing trigger seek to word action
setCurrentWord(id);
}
}

getLast() {
const { ayahIds } = this.props;

Expand Down Expand Up @@ -365,13 +337,12 @@ export default class Surah extends Component {
}

renderAyahs() {
const { ayahs } = this.props;
const { ayahs, setCurrentWord } = this.props; // eslint-disable-line no-shadow

return Object.values(ayahs).map(ayah => (
<Ayah
ayah={ayah}
onWordClick={this.onWordClick}
onWordFocus={this.onWordFocus}
onWordClick={setCurrentWord}
key={`${ayah.surahId}-${ayah.ayahNum}-ayah`}
/>
));
Expand Down
Loading