summaryrefslogtreecommitdiff
path: root/Main.elm
blob: 961c13a7dbbb822b9735306923080a8eb4090421 (plain)
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
import Html exposing (..)
import Html.Attributes exposing (..)
import Http
import Task
import Date
import Time exposing (..)
import Json.Decode as Decode

main = Html.program
  { init          = (
    { lastFetch = 0
    , state     = Fetching
    , feed      = []
    }, fetch)
  , view          = view
  , update        = update
  , subscriptions = \_ -> Time.every minute Tick
  }


type alias Article =
  { title : String
  , feed  : String
  , ts    : Time
  , url   : String
  }

decodeArticle : Decode.Decoder Article
decodeArticle = Decode.map4 Article
  (Decode.field "title" Decode.string)
  (Decode.field "feed"  Decode.string)
  (Decode.field "ts"    Decode.float)
  (Decode.field "url"   Decode.string)


type State
  = Start
  | Current
  | Fetching
  | FetchError

type alias Model =
  { lastFetch : Time
  , state     : State
  , feed      : List Article
  }

type Msg
  = Tick Time
  | Data (Result Http.Error (List Article))
  | SetTime Time


fetch : Cmd Msg
fetch = Http.send Data (Http.get "feeds.json" (Decode.list decodeArticle))


update : Msg -> Model -> (Model, Cmd Msg)
update msg model = case msg of
  Tick _       -> ({ model | state = Fetching   }, fetch)
  Data (Err _) -> ({ model | state = FetchError }, Cmd.none)
  SetTime t    -> ({ model | lastFetch = t      }, Cmd.none)
  Data (Ok r)  ->
    ( { model | state = Current, feed = r }
    , Task.perform SetTime now
    )


-- Surely there must be an easier way to do this
fmtts : Time -> String
fmtts t = let d = Date.fromTime t in
     toString (Date.day d)
  ++ " "
  ++ toString (Date.month d)
  ++ " "
  ++ toString (Date.year d)
  ++ " "
  ++ String.padLeft 2 '0' (toString (Date.hour d))
  ++ ":"
  ++ String.padLeft 2 '0' (toString (Date.minute d))


view : Model -> Html Msg
view model =
  let
    state = em [ class (toString model.state) ]
      [ if model.lastFetch == 0
        then text "Loading feeds..."
        else text (fmtts model.lastFetch) ]
    item n = article []
      [ a [href n.url] [ text n.title ]
      , i []
        [ text (fmtts (n.ts*1000))
        , text " - "
        , text n.feed
        ]
      ]
  in div [] (state :: List.map item model.feed)