Skip to content

Instantly share code, notes, and snippets.

@leordev
Last active December 11, 2017 04:51
Show Gist options
  • Save leordev/ddfa7bf93e695146e625349ac7ae8f8e to your computer and use it in GitHub Desktop.
Save leordev/ddfa7bf93e695146e625349ac7ae8f8e to your computer and use it in GitHub Desktop.
module Main exposing (..)
import Html exposing (..)
import Http
import Json.Decode as Decode
import Json.Decode.Pipeline exposing (decode, required, hardcoded)
main =
Html.program
{ init = initialize
, view = view
, update = update
, subscriptions = \_ -> Sub.none
}
-- constants
maxStories : Int
maxStories =
30
-- model
type alias Story =
{ id : Int
, by : String
, score : Int
, newsType : String
, url : String
, title : String
, tags : Maybe StoryTags
}
type alias StoryTags =
{ title : String
, description : String
, image : Maybe String
, favicon : String
}
type alias Model =
{ stories : List Story
, loading : Bool
, tempList : List Int
, error : String
}
initialize : ( Model, Cmd Msg )
initialize =
( Model [] True [] "", getTopStories )
-- Requests
getTopStories : Cmd Msg
getTopStories =
let
url =
"https://hacker-news.firebaseio.com/v0/topstories.json"
in
Http.send LoadStories (Http.get url storiesDecoder)
getStory : Int -> Cmd Msg
getStory storyId =
let
url =
"https://hacker-news.firebaseio.com/v0/item/"
++ (toString storyId)
++ ".json"
in
Http.get url storyDecoder
|> Http.send LoadStory
getStoryTags : Story -> Cmd Msg
getStoryTags story =
let
url =
"https://api.urlmeta.org/?url="
++ story.url
in
Http.get url storyTagDecoder
|> Http.send LoadStoryTag
storiesDecoder : Decode.Decoder (List Int)
storiesDecoder =
Decode.list Decode.int
storyDecoder : Decode.Decoder Story
storyDecoder =
decode Story
|> required "id" Decode.int
|> required "by" Decode.string
|> required "score" Decode.int
|> required "type" Decode.string
|> required "url" Decode.string
|> required "title" Decode.string
|> hardcoded Nothing
storyTagDecoder : Decode.Decoder StoryTags
storyTagDecoder =
decode StoryTags
|> required "title" Decode.string
|> required "description" Decode.string
|> required "image" (Decode.nullable Decode.string)
|> required "favicon" Decode.string
-- update
type Msg
= LoadStories (Result Http.Error (List Int))
| LoadStory (Result Http.Error Story)
| LoadStoryTag (Result Http.Error ( Story, StoryTags ))
| RefreshNews
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
RefreshNews ->
( { model | loading = True, error = "" }, getTopStories )
LoadStories (Ok stories) ->
getStoriesDetails model stories
LoadStories (Err error) ->
( { model | loading = False, error = (toString error) }, Cmd.none )
LoadStory (Ok story) ->
( { model | stories = story :: model.stories }, getStoryTags story )
LoadStory (Err error) ->
( { model | loading = False, error = (toString error) }, Cmd.none )
LoadStoryTag (Ok ( story, tags )) ->
let
x =
Debug.log "story " story
x2 =
Debug.log "tags" tags
in
( model, Cmd.none )
LoadStoryTag (Err error) ->
( { model | error = (toString error) }, Cmd.none )
getStoriesDetails : Model -> List Int -> ( Model, Cmd Msg )
getStoriesDetails model stories =
let
batch =
stories
|> List.take maxStories
|> List.map getStory
in
( { model | tempList = stories }, Cmd.batch batch )
-- view
view : Model -> Html Msg
view model =
text (toString model.loading)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment