Compare commits
No commits in common. "ee62b850087d3e51eb19806a0d70aed8ef110be6" and "f28b5b1c50ecdcab96298c275e579a43d095e086" have entirely different histories.
ee62b85008
...
f28b5b1c50
30
package-lock.json
generated
30
package-lock.json
generated
@ -5475,14 +5475,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-parse-stringify2": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
|
||||
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
|
||||
"requires": {
|
||||
"void-elements": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"html-webpack-plugin": {
|
||||
"version": "4.0.0-beta.11",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz",
|
||||
@ -5658,14 +5650,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"i18next": {
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-19.1.0.tgz",
|
||||
"integrity": "sha512-ISbmukX4L6Dz0QoH9+EW1AnBw7j+NRLoMu9uLPMaNSSTP9Eie9/oUL0dOyWX15baB3gYOpkHJpGZRHOqcnl0ew==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@ -9513,15 +9497,6 @@
|
||||
"integrity": "sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==",
|
||||
"dev": true
|
||||
},
|
||||
"react-i18next": {
|
||||
"version": "11.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.3.1.tgz",
|
||||
"integrity": "sha512-S/CWHcnew1lXo8HeniGhBU5kTmPhZ4w4rtA4m/gDN07soCtKKYSAcLNm7zhwjI2OSR4Skd0vOtzNp/FzEEjxIw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"html-parse-stringify2": "2.0.1"
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.8.0.tgz",
|
||||
@ -11573,11 +11548,6 @@
|
||||
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"void-elements": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
||||
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
|
||||
},
|
||||
"walk-back": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz",
|
||||
|
@ -18,10 +18,8 @@
|
||||
"axios": "^0.19.0",
|
||||
"classnames": "^2.2.6",
|
||||
"debounce": "^1.2.0",
|
||||
"i18next": "^19.1.0",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-i18next": "^11.3.1",
|
||||
"react-icons": "^3.8.0",
|
||||
"react-redux": "^7.1.3",
|
||||
"redux": "^4.0.4",
|
||||
|
30
src/App.css
30
src/App.css
@ -1,30 +0,0 @@
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
line-height: 1.5;
|
||||
background-color: #fce6cb;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 2px solid white;
|
||||
margin-bottom: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
footer {
|
||||
border-top: 2px solid white;
|
||||
margin-top: 1em;
|
||||
padding: 0 10px;
|
||||
}
|
16
src/App.js
16
src/App.js
@ -1,25 +1,13 @@
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { RsvpReader } from './components/RsvpReader'
|
||||
import { GutenbergSearch } from './components/GutenbergSearch'
|
||||
|
||||
import './App.css'
|
||||
import { LangSelect } from './components/LangSelect'
|
||||
|
||||
export const App = () => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<h1>{t('title')}</h1>
|
||||
<LangSelect />
|
||||
</header>
|
||||
<main>
|
||||
<RsvpReader></RsvpReader>
|
||||
<GutenbergSearch></GutenbergSearch>
|
||||
</main>
|
||||
<footer>Made by Alfred Melch</footer>
|
||||
<RsvpReader></RsvpReader>
|
||||
<GutenbergSearch></GutenbergSearch>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ const Book = ({ entry }) => {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{id} {title.join(' – ')}
|
||||
{id} {title.join(' - ')}
|
||||
</div>
|
||||
<div>{author[0]}</div>
|
||||
<div>{language.join(' – ')}</div>
|
||||
<div>{language.join(' - ')}</div>
|
||||
<div>
|
||||
<button onClick={handleClick}>Load</button>
|
||||
</div>
|
||||
|
@ -1,22 +0,0 @@
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { languages } from '../i18n'
|
||||
|
||||
export const LangSelect = () => {
|
||||
const { i18n } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<select
|
||||
value={i18n.language}
|
||||
onChange={evt => i18n.changeLanguage(evt.target.value)}
|
||||
>
|
||||
{languages.map(lng => (
|
||||
<option key={lng} value={lng}>
|
||||
{lng}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</>
|
||||
)
|
||||
}
|
@ -5,12 +5,10 @@ import { debounce } from 'debounce'
|
||||
import { setMaxLength, setWpm, setOffset, setLang } from '../store/actions'
|
||||
import { Slider } from './Slider'
|
||||
import { selectOffset, selectLang } from '../store/selectors'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const availableLanguages = ['en', 'de']
|
||||
|
||||
export const Options = () => {
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useDispatch()
|
||||
const maxLength = useSelector(state => state.maxLength)
|
||||
const wpm = useSelector(state => state.wpm)
|
||||
@ -19,23 +17,23 @@ export const Options = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{t('options.title')}</h2>
|
||||
<h2>Options</h2>
|
||||
<Slider
|
||||
title={t('options.maxLength')}
|
||||
title={'Maximum segment length'}
|
||||
min={3}
|
||||
max={15}
|
||||
value={maxLength}
|
||||
onChange={debounce(val => dispatch(setMaxLength(val)), 100)}
|
||||
/>
|
||||
<Slider
|
||||
title={t('options.wpm')}
|
||||
title={'Words per minute'}
|
||||
min={100}
|
||||
max={1000}
|
||||
value={wpm}
|
||||
onChange={debounce(val => dispatch(setWpm(val)), 50)}
|
||||
/>
|
||||
<Slider
|
||||
title={t('options.offset')}
|
||||
title={'Offset from center'}
|
||||
min={-50}
|
||||
max={50}
|
||||
value={offset}
|
||||
|
@ -1,9 +0,0 @@
|
||||
.area {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.load {
|
||||
width: 100%;
|
||||
}
|
@ -3,8 +3,6 @@ import { useDispatch } from 'react-redux'
|
||||
|
||||
import { setText } from '../store/actions.js'
|
||||
|
||||
import styles from './TextInput.css'
|
||||
|
||||
const lorem =
|
||||
'Excepteur aliqua cupidatat ullamco laboris cupidatat elit sint cillum incididunt. Anim sit excepteur laboris commodo ullamco consequat tempor. Velit elit eiusmod aute aliquip amet sunt minim deserunt voluptate esse ea sint. Commodo ipsum dolor dolor Lorem et consectetur minim ut in voluptate. Nulla qui consectetur nostrud sint anim minim duis qui amet. Ipsum reprehenderit eiusmod quis Lorem. Consectetur ipsum quis incididunt proident ea sit mollit veniam in excepteur.'
|
||||
|
||||
@ -14,13 +12,10 @@ export const TextInput = () => {
|
||||
return (
|
||||
<div>
|
||||
<textarea
|
||||
className={styles.area}
|
||||
defaultValue={text}
|
||||
onInput={e => setTextState(e.target.value)}
|
||||
></textarea>
|
||||
<button className={styles.load} onClick={() => dispatch(setText(text))}>
|
||||
Load
|
||||
</button>
|
||||
<button onClick={() => dispatch(setText(text))}>Load</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"title": "Der schnelle leser",
|
||||
"search": "Suche",
|
||||
"options": {
|
||||
"title": "Optionen",
|
||||
"maxLength": "Maximale Segmentlänge",
|
||||
"wpm": "Wörter pro Minute",
|
||||
"offset": "Versatz der Wortanzeige"
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"title": "The Fast Reader",
|
||||
"search": "Search",
|
||||
"options": {
|
||||
"title": "Options",
|
||||
"maxLength": "Maximum segment length",
|
||||
"wpm": "Words per minute",
|
||||
"offset": "Offset from center"
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
import i18n from 'i18next'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
import de from './de.json'
|
||||
import en from './en.json'
|
||||
|
||||
const resources = {
|
||||
en: { translation: en },
|
||||
de: { translation: de }
|
||||
}
|
||||
|
||||
console.log(de, en)
|
||||
i18n.use(initReactI18next).init({
|
||||
resources,
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
}
|
||||
})
|
||||
|
||||
export const languages = Object.keys(resources)
|
@ -7,8 +7,6 @@ import { Provider } from 'react-redux'
|
||||
import { App } from './App'
|
||||
import { store } from './store/index.js'
|
||||
|
||||
import './i18n'
|
||||
|
||||
function createRootElement() {
|
||||
const body = document.getElementsByTagName('body')[0]
|
||||
const root = document.createElement('div')
|
||||
|
@ -1,23 +0,0 @@
|
||||
import Axios from 'axios'
|
||||
|
||||
export async function search(searchTerm, maxResults = Infinity) {
|
||||
const regex = new RegExp(searchTerm, 'i')
|
||||
const result = []
|
||||
const data = await import('../../data/gutenberg.json').then(
|
||||
module => module.default
|
||||
)
|
||||
for (let entry of data) {
|
||||
if (regex.test(entry.title[0]) || regex.test(entry.author[0])) {
|
||||
result.push(entry)
|
||||
}
|
||||
|
||||
if (result.length >= maxResults) break
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getBook(bookId) {
|
||||
const url = `https://gutenberg.muperfredi.de/texts/${bookId}/stripped-body`
|
||||
const text = await Axios.get(url).then(res => res.data.body)
|
||||
return text
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
animation: rotation 2s linear infinite;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import React from 'react'
|
||||
import { FiLoader } from 'react-icons/fi'
|
||||
|
||||
import styles from './Spinner.css'
|
||||
|
||||
export const Spinner = () => {
|
||||
return <FiLoader className={styles.spinner} />
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user