-
Notifications
You must be signed in to change notification settings - Fork 0
/
TextFetch.elm
150 lines (110 loc) · 3.58 KB
/
TextFetch.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
port module TextFetch exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as App
import Json.Decode
import Http
import Task
import String
import Char
import Json.Decode exposing (at, string)
import Debug exposing (log)
import Utils
import List
--TODO: Store last page number for each text in the localStorage, So the user can continue where they left.
type alias Model =
{ options : List Option
, selectedOption : Maybe Option
, selectedText : Maybe Text
, page : Maybe Int
}
type alias Option =
{ url : String
, name : String
}
type alias Text =
List (List Char)
type Msg
= Fetch Option
| FetchSuccess Text
| FetchFailure Http.Error
| TurnPage
| FetchPageSuccess Int
wordsPerPage =
20
port urls : String -> Cmd msg
port pageSetter : ( String, Int ) -> Cmd msg
update : Msg -> Model -> ( Model, Cmd Msg, Maybe (List Char) )
update msg model =
case msg of
Fetch option ->
( { model | selectedOption = Just option }, getText option.url, Nothing )
FetchSuccess text ->
( { model | selectedText = (Just (log "t" text)) }
, urls (Maybe.withDefault (Option " " " ") model.selectedOption).url
, Nothing
)
FetchPageSuccess page ->
( { model | page = (Just (page - 1)) }
, Task.perform (\_ -> Debug.crash "This failure cannot happen.") identity (Task.succeed TurnPage)
, Nothing
)
FetchFailure _ ->
( model, Cmd.none, Nothing )
TurnPage ->
case ( model.selectedOption, model.selectedText, model.page ) of
( Just option, Just text, Just page ) ->
( { model | page = Just (page + 1) }
, pageSetter ( option.url, (page + 1) )
, let
newText =
text
|> List.drop (page * wordsPerPage)
|> List.take wordsPerPage
|> Utils.wordsToChars
in
if List.length newText > 0 then
Just newText
else
-- text is over
Nothing
)
( _, _, _ ) ->
( model, Cmd.none, Nothing )
selectedOptionDecoder =
Json.Decode.object2
Option
(at [ "target", "selectedOptions", "0", "id" ] string)
(at [ "target", "selectedOptions", "0", "value" ] string)
view : Model -> Html Msg
view model =
select [ on "change" (Json.Decode.map Fetch selectedOptionDecoder) ]
(List.map
(\opt ->
option [ id opt.url, value opt.name ] [ text opt.name ]
)
model.options
)
init =
Model
[ { name = "Select a book..", url = "/nothig.txt" }
, { name = "Pride and Perjudice", url = "/books/pride.txt" }
, { name = "The Picture of Dorian Gray", url = "/books/dorian.txt" }
]
Nothing
Nothing
Nothing
-- SUBSCRIPTIONS
subscriptions : ((Int -> Msg) -> Sub Msg) -> Model -> Sub Msg
subscriptions pageGetter model =
pageGetter FetchPageSuccess
-- HTTP
getText : String -> Cmd Msg
getText file =
Task.perform FetchFailure
FetchSuccess
((Http.getString file)
|> Task.map
(Utils.dropHeaders >> Utils.removeExtraNewLines >> Utils.words)
)