diff options
Diffstat (limited to 'src/Timer')
-rw-r--r-- | src/Timer/Model.elm | 27 | ||||
-rw-r--r-- | src/Timer/Model/State.elm | 8 | ||||
-rw-r--r-- | src/Timer/Msg.elm | 13 | ||||
-rw-r--r-- | src/Timer/Update.elm | 56 | ||||
-rw-r--r-- | src/Timer/View.elm | 175 |
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 |