lokalnie gradle dziala
Deploy to FTP / deploy (push) Successful in 5s
Build APK / build (push) Successful in 1m51s

This commit is contained in:
Sebastian Molenda
2026-05-27 00:13:35 +02:00
parent 3402bb1c13
commit 145c148bbc
618 changed files with 30116 additions and 4 deletions
@@ -0,0 +1,138 @@
// Nauka Czytania
;(function () {
// ms between line advances for each speed level (0 = manual)
const SPEEDS_MS = [0, 3500, 2000, 1000]
const SPEED_LABELS = ['Pauza', 'Wolno', 'Średnio', 'Szybko']
let yOffset = 0
let lineH = 80 // recalculated after render
let maxOffset = 0
let speedIdx = 0
let autoTimer = null
const listWrap = document.getElementById('list-wrap')
const readWrap = document.getElementById('read-wrap')
const textList = document.getElementById('text-list')
const customInput = document.getElementById('custom-input')
const customStartBtn = document.getElementById('custom-start-btn')
const readBackBtn = document.getElementById('read-back-btn')
const readTitleEl = document.getElementById('read-title')
const speedBtn = document.getElementById('speed-btn')
const readViewport = document.getElementById('read-viewport')
const readTextEl = document.getElementById('read-text')
const nextLineBtn = document.getElementById('next-line-btn')
let progressBar = null
// ── Load text list from dyktanda.json ────────────────────────────────────
fetch('json/dyktanda.json')
.then(r => r.json())
.then(data => {
data.forEach(item => {
const btn = document.createElement('button')
btn.className = 'list-item-btn'
btn.textContent = item.name
btn.addEventListener('click', () => startReading(item.name, item.text))
textList.appendChild(btn)
})
})
.catch(() => {
textList.innerHTML = '<p style="color:var(--muted);padding:8px 0">Nie udało się wczytać tekstów.</p>'
})
customStartBtn.addEventListener('click', () => {
const txt = customInput.value.trim()
if (!txt) return
startReading('Własny', txt)
})
// ── Start reading ─────────────────────────────────────────────────────────
function startReading(title, text) {
yOffset = 0
speedIdx = 0
clearInterval(autoTimer)
autoTimer = null
readTitleEl.textContent = title
readTextEl.textContent = text
readTextEl.style.transform = 'translateY(0)'
speedBtn.textContent = SPEED_LABELS[0]
progressBar.style.width = '0%'
listWrap.classList.add('hidden')
readWrap.classList.remove('hidden')
// measure real line height after layout
requestAnimationFrame(() => {
requestAnimationFrame(() => {
const cs = getComputedStyle(readTextEl)
const lhVal = cs.lineHeight
lineH = (lhVal === 'normal')
? parseFloat(cs.fontSize) * 1.35
: parseFloat(lhVal)
maxOffset = Math.max(0, readTextEl.offsetHeight - lineH)
updateNextBtn()
updateProgressBar()
})
})
}
// ── Back to list ──────────────────────────────────────────────────────────
readBackBtn.addEventListener('click', () => {
const active = yOffset > 0 || autoTimer !== null
if (active && !confirm('Wrócić do listy tekstów?')) return
clearInterval(autoTimer)
autoTimer = null
readWrap.classList.add('hidden')
listWrap.classList.remove('hidden')
// Reset speed to manual on exit
speedIdx = 0;
})
// ── Speed selector ────────────────────────────────────────────────────────
speedBtn.addEventListener('click', () => {
clearInterval(autoTimer)
autoTimer = null
speedIdx = (speedIdx + 1) % SPEEDS_MS.length
speedBtn.textContent = SPEED_LABELS[speedIdx]
if (SPEEDS_MS[speedIdx] > 0 && yOffset < maxOffset) {
autoTimer = setInterval(advanceLine, SPEEDS_MS[speedIdx])
}
})
// ── Manual line advance ───────────────────────────────────────────────────
nextLineBtn.addEventListener('click', advanceLine)
// ── Core scroll logic ─────────────────────────────────────────────────────
function advanceLine() {
if (yOffset >= maxOffset) {
stopAutoAtEnd()
return
}
yOffset = Math.min(yOffset + lineH, maxOffset)
readTextEl.style.transform = `translateY(${-yOffset}px)`
updateNextBtn()
updateProgressBar()
if (yOffset >= maxOffset) stopAutoAtEnd()
}
function stopAutoAtEnd() {
if (autoTimer !== null) {
clearInterval(autoTimer)
autoTimer = null
speedIdx = 0
speedBtn.textContent = SPEED_LABELS[0]
}
updateNextBtn()
}
function updateNextBtn() {
nextLineBtn.disabled = yOffset >= maxOffset
}
function updateProgressBar() {
const progress = maxOffset > 0 ? (yOffset / maxOffset) * 100 : 100
if (!progressBar) progressBar = document.getElementById('read-progress-bar-inner')
if (progressBar) progressBar.style.width = `${progress}%`
}
})()