Compare commits
5 Commits
3fb84e0de0
...
f28b5b1c50
Author | SHA1 | Date | |
---|---|---|---|
f28b5b1c50 | |||
2e4cdbe67b | |||
f87acd5514 | |||
797ef6a1fa | |||
247ba964ec |
8
package-lock.json
generated
8
package-lock.json
generated
@ -9796,6 +9796,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
|
||||||
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
|
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
|
||||||
},
|
},
|
||||||
|
"reselect-tools": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect-tools/-/reselect-tools-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-+RGguS8ph21y04l6YwQwL+VfJ/c0qyZKCkhCd5ZwbNJ/lklsJml3CIim+uaG/t+7jYZQcwDW4bk5+VzTeuzwtw==",
|
||||||
|
"requires": {
|
||||||
|
"reselect": "4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.13.1",
|
"version": "1.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
"react-redux": "^7.1.3",
|
"react-redux": "^7.1.3",
|
||||||
"redux": "^4.0.4",
|
"redux": "^4.0.4",
|
||||||
"regenerator-runtime": "^0.13.3",
|
"regenerator-runtime": "^0.13.3",
|
||||||
"reselect": "^4.0.0"
|
"reselect": "^4.0.0",
|
||||||
|
"reselect-tools": "0.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.7.5",
|
"@babel/core": "^7.7.5",
|
||||||
|
@ -4,8 +4,7 @@ import { useSelector, useDispatch } from 'react-redux'
|
|||||||
import {
|
import {
|
||||||
selectHasNextSegment,
|
selectHasNextSegment,
|
||||||
selectRunning,
|
selectRunning,
|
||||||
selectInterval,
|
selectInterval
|
||||||
selectCurrentSegment
|
|
||||||
} from '../store/selectors'
|
} from '../store/selectors'
|
||||||
import { incrementSegment, stop, pause, start } from '../store/actions'
|
import { incrementSegment, stop, pause, start } from '../store/actions'
|
||||||
import { FiPlay, FiPause, FiSquare } from 'react-icons/fi'
|
import { FiPlay, FiPause, FiSquare } from 'react-icons/fi'
|
||||||
@ -17,8 +16,6 @@ export const PlayerControl = () => {
|
|||||||
const running = useSelector(selectRunning)
|
const running = useSelector(selectRunning)
|
||||||
const hasNext = useSelector(selectHasNextSegment)
|
const hasNext = useSelector(selectHasNextSegment)
|
||||||
const interval = useSelector(selectInterval)
|
const interval = useSelector(selectInterval)
|
||||||
const segment = useSelector(selectCurrentSegment)
|
|
||||||
console.log(interval, segment)
|
|
||||||
|
|
||||||
useInterval(
|
useInterval(
|
||||||
() => {
|
() => {
|
||||||
|
@ -30,7 +30,9 @@ export const RsvpReader = () => {
|
|||||||
<Options></Options>
|
<Options></Options>
|
||||||
<TotalTime />
|
<TotalTime />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.item}>{/* <TextOutput /> */}</div>
|
<div className={styles.item}>
|
||||||
|
<TextOutput />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.current {
|
.current {
|
||||||
text-decoration: underline;
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sentenceBeginning {
|
.sentenceBeginning {
|
||||||
|
@ -5,17 +5,23 @@ import classNames from 'classnames'
|
|||||||
import { getNextSmallerNumber } from '../lib/array-util.js'
|
import { getNextSmallerNumber } from '../lib/array-util.js'
|
||||||
import {
|
import {
|
||||||
selectParsedText,
|
selectParsedText,
|
||||||
selectCurrentSegmentIndex
|
selectCurrentSegmentIndex,
|
||||||
|
selectDisplayMode,
|
||||||
|
selectSegmentWindow
|
||||||
} from '../store/selectors.js'
|
} from '../store/selectors.js'
|
||||||
|
|
||||||
import styles from './TextOutput.css'
|
import styles from './TextOutput.css'
|
||||||
|
|
||||||
export const TextOutput = () => {
|
export const TextOutput = () => {
|
||||||
const { segments, sentences, words } = useSelector(selectParsedText)
|
const { segments, offset } = useSelector(selectSegmentWindow)
|
||||||
|
const { sentences, words } = useSelector(selectParsedText)
|
||||||
const curSegment = useSelector(selectCurrentSegmentIndex)
|
const curSegment = useSelector(selectCurrentSegmentIndex)
|
||||||
|
const mode = useSelector(selectDisplayMode)
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div>
|
<div>
|
||||||
{segments.map((segment, idx) => {
|
{segments.map((segment, idx) => {
|
||||||
|
idx = idx + offset
|
||||||
const isCurrent = curSegment === idx
|
const isCurrent = curSegment === idx
|
||||||
const isWordStart = words.includes(idx)
|
const isWordStart = words.includes(idx)
|
||||||
const wordBeginning = isWordStart
|
const wordBeginning = isWordStart
|
||||||
@ -38,5 +44,6 @@ export const TextOutput = () => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
const sentenceEndings = '.!?:;'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object containing the segmented text and metainfo about word and
|
* Returns an object containing the segmented text and metainfo about word and
|
||||||
* sentence beginnings
|
* sentence beginnings
|
||||||
@ -24,7 +26,9 @@ export function parseText(text, maxLength) {
|
|||||||
curIdx += fragments.length
|
curIdx += fragments.length
|
||||||
|
|
||||||
// set flag if next word is sentence beginning
|
// set flag if next word is sentence beginning
|
||||||
sentenceFlag = word.endsWith('.')
|
sentenceFlag = sentenceEndings
|
||||||
|
.split('')
|
||||||
|
.some(ending => word.endsWith(ending))
|
||||||
}
|
}
|
||||||
|
|
||||||
return { segments, words, sentences }
|
return { segments, words, sentences }
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
import { createStore } from 'redux'
|
import { createStore } from 'redux'
|
||||||
|
import { registerSelectors, getStateWith } from 'reselect-tools'
|
||||||
|
|
||||||
import { reducerFn, initialState } from './reducer'
|
import { reducerFn, initialState } from './reducer'
|
||||||
|
import * as selectors from './selectors'
|
||||||
|
|
||||||
export const store = createStore(
|
export const store = createStore(
|
||||||
reducerFn,
|
reducerFn,
|
||||||
initialState,
|
initialState,
|
||||||
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
|
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
registerSelectors(selectors)
|
||||||
|
getStateWith(() => store.getState())
|
||||||
|
@ -15,7 +15,15 @@ export const initialState = {
|
|||||||
wpm: 300,
|
wpm: 300,
|
||||||
offset: -15,
|
offset: -15,
|
||||||
running: false,
|
running: false,
|
||||||
lang: 'en'
|
lang: 'en',
|
||||||
|
textDisplay: {
|
||||||
|
mode: 'pagination',
|
||||||
|
options: {
|
||||||
|
pagination: { pageLength: 50 },
|
||||||
|
segments: { prev: 9, next: 40 },
|
||||||
|
sentences: { prev: 1, next: 8 }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reducer = {
|
const reducer = {
|
||||||
|
@ -11,9 +11,10 @@ const notNull = val => val != null
|
|||||||
// parsedText selectors
|
// parsedText selectors
|
||||||
|
|
||||||
export const selectMaxLength = state => state.maxLength
|
export const selectMaxLength = state => state.maxLength
|
||||||
|
export const selectOriginalText = state => state.originalText
|
||||||
|
|
||||||
export const selectParsedText = createSelector(
|
export const selectParsedText = createSelector(
|
||||||
state => state.originalText,
|
selectOriginalText,
|
||||||
selectMaxLength,
|
selectMaxLength,
|
||||||
(originalText, maxLength) => parseText(originalText, maxLength)
|
(originalText, maxLength) => parseText(originalText, maxLength)
|
||||||
)
|
)
|
||||||
@ -166,3 +167,26 @@ export const selectTotalTime = createSelector(selectIntervals, intervals =>
|
|||||||
// player
|
// player
|
||||||
|
|
||||||
export const selectRunning = state => state.running
|
export const selectRunning = state => state.running
|
||||||
|
|
||||||
|
// text display
|
||||||
|
|
||||||
|
export const selectDisplayMode = state => state.textDisplay.mode
|
||||||
|
export const selectDisplayOptions = state => state.textDisplay.options
|
||||||
|
export const selectCurrentDisplayOptions = createSelector(
|
||||||
|
selectDisplayMode,
|
||||||
|
selectDisplayOptions,
|
||||||
|
(mode, options) => options[mode]
|
||||||
|
)
|
||||||
|
|
||||||
|
export const selectSegmentWindow = createSelector(
|
||||||
|
selectDisplayMode,
|
||||||
|
selectCurrentDisplayOptions,
|
||||||
|
selectCurrentSegmentIndex,
|
||||||
|
selectSegments,
|
||||||
|
(mode, options, idx, segments) => {
|
||||||
|
const page = Math.floor(idx / options.pageLength)
|
||||||
|
const start = page * options.pageLength
|
||||||
|
const end = page * options.pageLength + options.pageLength
|
||||||
|
return { offset: start, segments: segments.slice(start, end) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user