aboutsummaryrefslogtreecommitdiff
path: root/src/Timer
diff options
context:
space:
mode:
Diffstat (limited to 'src/Timer')
-rw-r--r--src/Timer/Model.elm27
-rw-r--r--src/Timer/Model/State.elm8
-rw-r--r--src/Timer/Msg.elm13
-rw-r--r--src/Timer/Update.elm56
-rw-r--r--src/Timer/View.elm175
5 files changed, 279 insertions, 0 deletions
diff --git a/src/Timer/Model.elm b/src/Timer/Model.elm
new file mode 100644
index 0000000..89af67e
--- /dev/null
+++ b/src/Timer/Model.elm
@@ -0,0 +1,27 @@
+module Timer.Model exposing
+ ( Timer
+ , init
+ )
+
+import List
+import Time exposing (Time)
+
+import Timer.Model.State exposing (..)
+
+type alias Timer =
+ { creationTime : Time
+ , name : Maybe String
+ , initialTime : Time
+ , time : Time
+ , state : State
+ }
+
+init : Time -> Timer
+init creationTime =
+ let initialTime = 5 * 60 * 1000
+ in { creationTime = creationTime
+ , name = Nothing
+ , initialTime = initialTime
+ , time = initialTime
+ , state = Idle
+ }
diff --git a/src/Timer/Model/State.elm b/src/Timer/Model/State.elm
new file mode 100644
index 0000000..1162e59
--- /dev/null
+++ b/src/Timer/Model/State.elm
@@ -0,0 +1,8 @@
+module Timer.Model.State exposing
+ ( State(..)
+ )
+
+type State =
+ Idle
+ | Running
+ | Ringing
diff --git a/src/Timer/Msg.elm b/src/Timer/Msg.elm
new file mode 100644
index 0000000..150d4fc
--- /dev/null
+++ b/src/Timer/Msg.elm
@@ -0,0 +1,13 @@
+module Timer.Msg exposing
+ ( Msg(..)
+ )
+
+import Time exposing (Time)
+
+type Msg =
+ Rename String
+ | Pause
+ | ToggleRunning
+ | Stop
+ | SetTime Time
+ | SubstractTime Time
diff --git a/src/Timer/Update.elm b/src/Timer/Update.elm
new file mode 100644
index 0000000..31e8a43
--- /dev/null
+++ b/src/Timer/Update.elm
@@ -0,0 +1,56 @@
+module Timer.Update exposing
+ ( updateTimer
+ )
+
+import Time exposing (Time)
+
+import Model.Id exposing (..)
+
+import Timer.Model exposing (..)
+import Timer.Model.State exposing (..)
+import Timer.Msg exposing (..)
+
+updateTimer : Msg -> Timer -> Timer
+updateTimer msg timer =
+ case msg of
+
+ Rename name ->
+ { timer | name = Just name }
+
+ Pause ->
+ { timer | state = Idle }
+
+ ToggleRunning ->
+ { timer
+ | state =
+ if timer.time > 0 && timer.state == Idle
+ then Running
+ else Idle
+ }
+
+ Stop ->
+ { timer
+ | time = timer.initialTime
+ , state = Idle
+ }
+
+ SetTime time ->
+ { timer
+ | initialTime = time
+ , time = time
+ }
+
+ SubstractTime time ->
+ if timer.state == Running
+ then
+ let newTime = timer.time - time
+ in if newTime <= 0.0
+ then
+ { timer
+ | time = 0.0
+ , state = Ringing
+ }
+ else
+ { timer | time = newTime }
+ else
+ timer
diff --git a/src/Timer/View.elm b/src/Timer/View.elm
new file mode 100644
index 0000000..561ae8f
--- /dev/null
+++ b/src/Timer/View.elm
@@ -0,0 +1,175 @@
+module Timer.View exposing
+ ( view
+ )
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Time exposing (Time)
+import Maybe
+import List
+import String
+
+import Msg exposing (Msg)
+
+import Model exposing (..)
+import Model.Id exposing (..)
+
+import Timer.Model exposing (..)
+import Timer.Model.State exposing (..)
+import Timer.Update exposing (..)
+import Timer.Msg as Timer
+
+import Edition.Model exposing (..)
+import Edition.Model.Name exposing (..)
+import Edition.Model.Time exposing (..)
+
+import Update exposing (..)
+
+import Utils.Maybe exposing (..)
+
+view : Model -> (Id, Timer) -> Html Msg
+view model (id, timer) =
+ div
+ [ [ ("timer", True)
+ , ("isRinging", timer.state == Ringing)
+ , ("isRunning", timer.state == Running)
+ ]
+ |> classList
+ ]
+ [ renderMaybeEdition model id Name (nameBlockReadOnly id timer) (nameBlockEdition id timer)
+ , renderMaybeEdition model id Time (timeBlockReadOnly (id, timer)) (timeBlockEdition (id, timer))
+ , playPauseTimer (id, timer)
+ , stopTimer (id, timer)
+ , removeTimer (id, timer)
+ ]
+
+nameBlockReadOnly : Id -> Timer -> Html Msg
+nameBlockReadOnly id timer =
+ div
+ [ class "name"
+ , onClick (Msg.Edit id Name)
+ ]
+ [ text (timerName id timer) ]
+
+nameBlockEdition : Id -> Timer -> Edition -> Html Msg
+nameBlockEdition id timer edition =
+ div
+ [ [ ("name", True)
+ , ("edition", True)
+ , ("empty", isEmpty edition)
+ ]
+ |> classList
+ , onClick Msg.NoOp
+ ]
+ [ if isEmpty edition
+ then
+ text (timerName id timer)
+ else
+ edition.chars
+ |> renderNameEdition
+ |> flip String.append "_"
+ |> text
+ ]
+
+timerName : Id -> Timer -> String
+timerName id = Maybe.withDefault ("Timer " ++ toString id) << .name
+
+timeBlockReadOnly : (Id, Timer) -> Html Msg
+timeBlockReadOnly (id, timer) =
+ div
+ [ class "time"
+ , onClick (Msg.Edit id Time)
+ ]
+ [ timeWithProgressBar (id, timer) ]
+
+timeBlockEdition : (Id, Timer) -> Edition -> Html Msg
+timeBlockEdition (id, timer) edition =
+ div
+ [ [ ("time", True)
+ , ("edition", True)
+ , ("empty", isEmpty edition)
+ ]
+ |> classList
+ , onClick Msg.NoOp
+ ]
+ [ if isEmpty edition
+ then
+ timeWithProgressBar (id, timer)
+ else
+ text (editionView edition.chars)
+ ]
+
+editionView : List Char -> String
+editionView numbers =
+ let (minutes, seconds) = toMinutesAndSeconds numbers
+ in minutes ++ " : " ++ seconds
+
+timeView : Time -> String
+timeView time =
+ let totalSeconds = ceiling (time / 1000)
+ totalMinutes = totalSeconds // 60
+ restSeconds = totalSeconds `rem` 60
+ in (String.padLeft 2 '0' (toString totalMinutes)) ++ " : " ++ (String.padLeft 2 '0' (toString restSeconds))
+
+timeWithProgressBar : (Id, Timer) -> Html Msg
+timeWithProgressBar (id, timer) =
+ div
+ []
+ [ span
+ [ class "progressBar"
+ , let width =
+ 1 - timer.time / timer.initialTime
+ |> (*) 1020
+ |> round
+ |> toString
+ |> flip String.append "px"
+ in style [ ("width", width) ]
+ , onClick (Msg.UpdateTimer id Timer.Stop)
+ ]
+ []
+ , span
+ [ class "text" ]
+ [ text (timeView timer.time) ]
+ ]
+
+playPauseTimer : (Id, Timer) -> Html Msg
+playPauseTimer (id, timer) =
+ button
+ [ class <| "playPause"
+ , onClick (Msg.UpdateTimer id Timer.ToggleRunning)
+ ]
+ [ let icon = if timer.state == Running then "fa-pause" else "fa-play"
+ in i
+ [ class <| "fa fa-fw " ++ icon ]
+ []
+ ]
+
+stopTimer : (Id, Timer) -> Html Msg
+stopTimer (id, timer) =
+ button
+ [ class <| "stop"
+ , onClick (Msg.UpdateTimer id Timer.Stop)
+ ]
+ [ i [ class "fa fa-fw fa-stop" ] [] ]
+
+removeTimer : (Id, Timer) -> Html Msg
+removeTimer (id, timer) =
+ button
+ [ class <| "remove"
+ , onClick (Msg.RemoveTimer id)
+ ]
+ [ i [ class "fa fa-fw fa-remove" ] [] ]
+
+renderMaybeEdition : Model -> Id -> Kind -> Html Msg -> (Edition -> Html Msg) -> Html Msg
+renderMaybeEdition model id kind readOnlyView editionView =
+ let maybeEdition = filterMaybe (\edition -> edition.id == id) model.edition
+ in case maybeEdition of
+ Just edition ->
+ if edition.kind == kind
+ then
+ editionView edition
+ else
+ readOnlyView
+ Nothing ->
+ readOnlyView