FlashReader
Czytnik pokazujący plik tekstowy słowo po słowie w ustawionym przez Ciebie tempie, który pamięta, gdzie skończyłeś.
- Wydany
- Zbierane dane
- Brak
- Cena
- Bezpłatny
O mnie
FlashReader otwiera lokalny plik .txt i pokazuje go słowo po słowie na środku ekranu, domyślnie co 500 ms. Czytający ustawia interwał, rozmiar liter, kolor liter i kolor tła. Cały tekst i pozycja słowa pozostają na urządzeniu, więc po restarcie ten sam plik otwiera się na tym samym słowie.
Ta strona opisuje wersję webową pod flashreader.fun: jedną stronę HTML z wbudowanym JavaScript. Skrypt nie wysyła żadnych żądań sieciowych i nie ma analityki. Aplikacja na Android w Google Play to osobny build, którego kod źródłowy nie jest tu omawiany.
Inżynieria jest niewielka i konkretna: timer, który potrafi zmienić tempo bez gubienia słowa, przechowywanie przeżywające restart oraz ustawienia stosowane i zapisywane w chwili zmiany.
FlashReader · skupione czytanie
co rozwiązano
Pętla słów
w produkcieCo to dajeUżytkownik wybiera plik tekstowy i czyta go słowo po słowie w równym tempie, a prędkość może zmienić w środku tekstu bez utraty miejsca.
- Problem
- Słowa muszą zmieniać się w równym, ustawionym przez użytkownika interwale, a interwał musi dać się zmienić w środku tekstu bez gubienia bieżącego słowa.
- Rozwiązanie
Jeden timer interwałowy przesuwa indeks po tablicy słów. Zmiana prędkości zatrzymuje ten timer i uruchamia nowy od tego samego indeksu.
- Technologie
Zamiana wybranego pliku tekstowego na ciąg słówCzytamy plik jako UTF-8 przez FileReader i dzielimy go po spacjach na tablicę
Plik pochodzi ze standardowego pola wyboru pliku ograniczonego do .txt, więc strona nie potrzebuje dostępu do systemu plików. action_load_file() czyta go przez readAsText(file, 'UTF-8') i dzieli wynik po pojedynczych spacjach; interpunkcja zostaje przy swoim słowie. Surowy tekst trafia też do saveFileContent() na potrzeby następnej sesji.
Pokazywanie jednego słowa na tick i nigdy dwóch timerów narazread() kończy się, jeśli timer już działa; każdy tick pokazuje słowo i zapisuje następny indeks
read() odmawia startu bez wczytanego tekstu ('Load text file to read!') i kończy się wcześniej, gdy ustawione jest is_going, więc dwukrotne naciśnięcie play nie uruchomi drugiego interwału. Każdy tick wpisuje text[position] do #text-zone i zapisuje position + 1. togglePlayPause() przełącza między read() a pause() i aktualizuje przycisk play.
Zmiana prędkości w środku czytania musi zadziałać natychmiastZatrzymujemy i uruchamiamy interwał z nowym okresem, zachowując indeks słowa
setInterval nie pozwala zmienić okresu. updateReadingSpeed() i handler change pola prędkości wywołują pause(), a potem read(), gdy czytanie jest aktywne. Indeks żyje w obiekcie czytnika, więc uruchomiony ponownie timer kontynuuje od następnego słowa. Wpisana wartość poniżej 1 jest resetowana do domyślnych 500 ms.
Koniec tekstu: zakończyć czysto albo zacząć od nowaNa końcu albo zatrzymujemy się z 'THE END!' i resetem do słowa 0, albo zawijamy do słowa 0
Tick sprawdza, czy słowo pod bieżącym indeksem jest undefined. Przy wyłączonym Loop czyści timer, pokazuje 'THE END!', zapisuje pozycję 0 i przełącza przycisk play z powrotem. Przy włączonym Loop ustawia indeks na 0 i działa dalej. Wybór Loop jest zapisywany jak pozostałe ustawienia.
Wznowienie po restarcie
w produkcieCo to dajeZamknij aplikację i wróć później: ten sam tekst otwiera się na tym samym słowie, z tym samym rozmiarem liter i prędkością, wszystko zapisane na urządzeniu.
- Problem
- Cały tekst, pozycja słowa i ustawienia wyświetlania muszą przetrwać zamknięcie strony lub aplikacji, bez serwera.
- Rozwiązanie
Tekst trafia do IndexedDB, pozycja i ustawienia do localStorage, a jedno i drugie jest odczytywane przy starcie.
- Technologie
Cała książka nie należy do localStorageSurowy tekst zapisujemy w IndexedDB pod jednym stałym kluczem; małe wartości trzymamy w localStorage
saveFileContent() wkłada tekst do magazynu 'files' bazy 'flashreader' (wersja 2) z id 'flashreader_last_text', więc nowy plik zastępuje stary. onupgradeneeded tworzy magazyn tylko wtedy, gdy go brakuje, więc otwarcie nad starszą wersją nie kończy się błędem.
Pozycja, kolory, rozmiar, prędkość, pętla i nazwa pliku zostają w localStorage, gdzie odczyty przy starcie są synchroniczne.
Ponowne otwarcie ostatniego pliku na słowie, na którym przerwano czytanieZapisujemy indeks przy każdym pokazanym słowie; przy starcie wczytujemy tekst i ten indeks
set_position() zapisuje indeks w localStorage (fr_position) przy każdym ticku, więc zamknięta lub zabita aplikacja traci najwyżej jedno słowo. Konstruktor najpierw odczytuje indeks; przy DOMContentLoaded getFileContent() wczytuje tekst z IndexedDB, dzieli go ponownie i pokazuje 'The last file, <name>, has been loaded' z prośbą o naciśnięcie play.
Zapisane wartości mogą być puste lub uszkodzoneKażdą wartość przywracamy osobno z wartościami domyślnymi: pozycja 0, rozmiar 48 px, prędkość 500 ms
Każdy klucz jest odczytywany i stosowany osobno, więc jedna zła wartość nie blokuje reszty. Nienumeryczna pozycja staje się 0, rozmiar czcionki, który parsuje się do 0, wraca do 48 px, prędkość, która parsuje się do 0, wraca do 500 ms. Kolory są zapisywane bez '#' i przywracane z nim, a następnie stosowane do tekstu i tła strony.
Wyświetlanie i sterowanie
w produkcieCo to dajeRozmiar liter i kolory zmieniają się podczas czytania, skróty klawiszowe sterują odtwarzaniem w przeglądarce, a czytający może cofnąć się o dziesięć słów lub przeskoczyć do dowolnego słowa.
- Problem
- Rozmiar liter i kolory muszą zmieniać się podczas czytania, a w przeglądarce na komputerze odtwarzaniem powinno dać się sterować z klawiatury.
- Rozwiązanie
Pola paska narzędzi stosują i zapisują każdą zmianę od razu; w przeglądarce skróty klawiszowe wywołują te same metody czytnika.
- Technologie
Rozmiar liter i kolory muszą zadziałać od razu i zostać zapamiętaneHandlery change ustawiają styl bezpośrednio i zapisują wartość; rozmiar poniżej 8 px staje się 8
Handler koloru czcionki ustawia kolor tekstu w #text-zone, handler tła ustawia tło body, a handler rozmiaru ustawia font-size w px z dolnym limitem 8. Każdy handler zapisuje wartość w localStorage w tym samym kroku, więc nie ma osobnej akcji zapisu.
W przeglądarce sterowanie z klawiatury nie może przewijać strony podczas czytaniaSpacja, F, strzałki w górę i w dół wywołują akcje czytnika i anulują domyślne zachowanie przeglądarki
W wersji przeglądarkowej Spacja przełącza play i pauzę, F przełącza pełny ekran, strzałka w górę przyspiesza słowa o 10 ms z dolnym limitem 50 ms, strzałka w dół zwalnia o 10 ms. preventDefault() powstrzymuje przeglądarkę przed przewijaniem lub wciśnięciem sfokusowanej kontrolki. Zmiany prędkości przechodzą przez updateReadingSpeed(), więc działający timer uruchamia się ponownie w nowym tempie.
Czytający pominął kilka słów i chce wrócićStrzałka w lewo (w przeglądarce) cofa o 10 słów, z limitem na 0; pole pozycji pozwala przeskoczyć do dowolnego słowa
skipBackwards() cofa indeks o 10, nigdy poniżej 0, od razu pokazuje to słowo i zapisuje pozycję. Pole pozycji na pasku narzędzi przyjmuje dowolny numer słowa; wartości ujemne stają się 0.
Pełny ekran działa inaczej w różnych przeglądarkach i powłokach aplikacjiPróbujemy standardowych i prefiksowanych Fullscreen API, a potem wtyczki Cordova Fullscreen, jeśli strona ją znajdzie
enterFullscreen() i exitFullscreen() przechodzą przez warianty standardowy, moz, webkit i ms. Gdy istnieje globalny obiekt Fullscreen, jak przy wtyczce pełnego ekranu Cordova, wywoływane jest także Fullscreen.show(). Przycisk i klawisz F używają tego samego sprawdzenia wszystkich czterech wariantów fullscreenElement.
Liczby
z produktu- Domyślne tempo 500 ms na słowo 120 słów na minutę.
- Najszybsze tempo 50 ms na słowo Do 1,200 słów na minutę z klawiatury.
- Krok prędkości 10 ms Strzałki w górę i w dół.