Skip to content

Instantly share code, notes, and snippets.

@dtjm
Last active February 8, 2016 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dtjm/9d3486138c7ea685002d to your computer and use it in GitHub Desktop.
Save dtjm/9d3486138c7ea685002d to your computer and use it in GitHub Desktop.
What is my IP? in Elm
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.1 <= v < 3.0.0",
"evancz/elm-html": "4.0.2 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/start-app": "2.0.2 <= v < 3.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}
module Main (..) where
import Effects
import Html
import Html.Attributes exposing (style)
import Html.Events as Events
import Http
import Json.Decode exposing ((:=))
import StartApp
import Task
import Time
initialModel =
{ ip = ""
, requestInProgress = False
}
view address model =
Html.div
[]
[ Html.h1 [] [ Html.text "what is my IP?" ]
, Html.pre [] [ Html.text model.ip ]
, Html.button
[ Events.onClick address Click ]
[ Html.text "Get my IP"
]
, statusView model
]
statusView model =
let
text =
case model.requestInProgress of
True ->
"request in progress"
False ->
"no request in progress"
in
Html.div
[ style [ ( "color", "red" ) ] ]
[ Html.text text ]
type Action
= Click
| HandleResponse Response
| Tick Time.Time
type Response
= Success String
| Fail String
ipDecoder =
("ip" := Json.Decode.string)
httpErrToAction : Http.Error -> Action
httpErrToAction e =
case e of
Http.Timeout ->
HandleResponse (Fail "timeout")
Http.NetworkError ->
HandleResponse (Fail "network error")
Http.UnexpectedPayload s ->
HandleResponse (Fail ("unexpected payload: " ++ s))
Http.BadResponse code msg ->
HandleResponse
(Fail
("bad response: HTTP "
++ toString code
++ ": "
++ msg
)
)
getMyIp : Effects.Effects Action
getMyIp =
Http.get
ipDecoder
"https://api.ipify.org?format=json"
|> Task.toResult
|> Task.map
(\x ->
case x of
Err y ->
httpErrToAction y
Ok y ->
HandleResponse (Success y)
)
|> Effects.task
update action model =
case action of
Click ->
( { model
| ip = "fetching..."
, requestInProgress = True
}
, Effects.batch [ getMyIp, Effects.tick Tick ]
)
HandleResponse r ->
case r of
Success ip ->
( { model
| ip = ip
, requestInProgress = False
}
, Effects.none
)
Fail reason ->
( { model
| ip = "failed: " ++ reason
, requestInProgress = False
}
, Effects.none
)
Tick t ->
let
newModel =
if model.requestInProgress then
{ model | ip = model.ip ++ "." }
else
model
tickEffect =
if model.requestInProgress then
Effects.tick Tick
else
Effects.none
in
( newModel, tickEffect )
ticker : Signal.Signal Action
ticker =
Signal.map (\t -> Tick t) (Time.every Time.millisecond)
app =
StartApp.start
{ init = ( initialModel, Effects.none )
, update = update
, view = view
, inputs = []
}
main =
app.html
port tasks : Signal (Task.Task Effects.Never ())
port tasks =
app.tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment