Compare commits

..

No commits in common. "ee62b850087d3e51eb19806a0d70aed8ef110be6" and "f28b5b1c50ecdcab96298c275e579a43d095e086" have entirely different histories.

16 changed files with 9 additions and 208 deletions

30
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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;
}

View File

@ -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>
</>
)
}

View File

@ -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>

View File

@ -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>
</>
)
}

View File

@ -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}

View File

@ -1,9 +0,0 @@
.area {
box-sizing: border-box;
width: 100%;
height: 300px;
}
.load {
width: 100%;
}

View File

@ -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>
)
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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)

View File

@ -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')

View File

@ -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
}

View File

@ -1,12 +0,0 @@
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.spinner {
animation: rotation 2s linear infinite;
}

View File

@ -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} />
}