aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--design/design.css23
-rw-r--r--src/Model/Timer.elm27
-rw-r--r--src/Model/TimerState.elm8
-rw-r--r--src/Update/Update.elm32
-rw-r--r--src/Update/UpdateTimer.elm18
-rw-r--r--src/View/Timer.elm124
-rw-r--r--src/View/View.elm10
7 files changed, 162 insertions, 80 deletions
diff --git a/design/design.css b/design/design.css
index ac34f6f..257a017 100644
--- a/design/design.css
+++ b/design/design.css
@@ -5,15 +5,17 @@
height: 150px;
line-height: 150px;
font-size: 70px;
- padding-left: 50px;
}
-.title > h1 {
+.title > button.title {
letter-spacing: 10px;
- float: left;
+ border: none;
+ padding-left: 50px;
+ padding-right: 50px;
+ font-family: "DejaVu Serif";
}
-.title > button {
+.title > button.addTimer {
float: right;
color: white;
border: 5px solid white;
@@ -43,6 +45,19 @@
border-radius: 2px;
}
+@keyframes ringing {
+ 30% {
+ background-color: #FED5AE;
+ }
+ 100% {
+ background-color: #FED5AE;
+ }
+}
+
+.timer.isRinging > :not(.remove) {
+ animation: ringing 2s linear infinite alternate;
+}
+
.timer.isRunning > .time {
color: #33AA22;
}
diff --git a/src/Model/Timer.elm b/src/Model/Timer.elm
index 754a62a..b73016d 100644
--- a/src/Model/Timer.elm
+++ b/src/Model/Timer.elm
@@ -8,12 +8,14 @@ module Model.Timer
import List
import Time (Time)
+import Model.TimerState (..)
+
type alias Timer =
{ creationTime : Time
, name : String
, initialTime : Time
, currentTime : Time
- , isRunning : Bool
+ , state : TimerState
}
initialTimer : Time -> String -> Timer
@@ -23,23 +25,22 @@ initialTimer creationTime name =
, name = name
, initialTime = initialTime
, currentTime = initTime initialTime
- , isRunning = False
+ , state = Idle
}
substractTimerTime : Time -> Timer -> Timer
substractTimerTime time timer =
- if timer.isRunning
+ if timer.state == Running
then
- if timer.currentTime - time <= 0.0
- then
- { timer
- | currentTime <- 0.0
- , isRunning <- False
- }
- else
- { timer
- | currentTime <- timer.currentTime - time
- }
+ let newTime = timer.currentTime - time
+ in if newTime <= 0.0
+ then
+ { timer
+ | currentTime <- 0.0
+ , state <- Ringing
+ }
+ else
+ { timer | currentTime <- newTime }
else
timer
diff --git a/src/Model/TimerState.elm b/src/Model/TimerState.elm
new file mode 100644
index 0000000..dbbcb80
--- /dev/null
+++ b/src/Model/TimerState.elm
@@ -0,0 +1,8 @@
+module Model.TimerState
+ ( TimerState(..)
+ ) where
+
+type TimerState =
+ Idle
+ | Running
+ | Ringing
diff --git a/src/Update/Update.elm b/src/Update/Update.elm
index 8285760..3bdcc2b 100644
--- a/src/Update/Update.elm
+++ b/src/Update/Update.elm
@@ -6,6 +6,7 @@ module Update.Update
import Signal
import Dict
+import Dict (Dict)
import Time (Time)
import Maybe
import Keyboard (KeyCode)
@@ -20,8 +21,11 @@ import Model.IdGenerator (..)
import Update.UpdateTimer (..)
import Update.UpdateTimerEdition (..)
+import Utils.Maybe (..)
+
type Action =
NoOp
+ | Initialize
| AddNewTimer
| DeltaTime Time
| UpdateTimer Id TimerAction
@@ -38,6 +42,8 @@ update : Action -> Model -> Model
update action model =
case action of
NoOp -> model
+ Initialize ->
+ initialModel model.currentTime
AddNewTimer ->
let (id, newTimerIdGenerator) = getId model.timerIdGenerator
timerName = "Timer " ++ (toString id)
@@ -51,14 +57,17 @@ update action model =
, timers <- substractTimersTime delta model.timers
}
UpdateTimer id action ->
- let inEdition =
- model.timerEdition
- |> Maybe.map (\timerEdition -> timerEdition.id == id)
- |> Maybe.withDefault False
- in if inEdition
- then
- model
- else
+
+ let maybeTimerEdition = filterMaybe (\timerEdition -> timerEdition.id == id) model.timerEdition
+ in case model.timerEdition of
+ Just timerEdition ->
+ { model
+ | timers <-
+ updateTimerTime timerEdition model.timers
+ |> Dict.update id (Maybe.map (updateTimer action))
+ , timerEdition <- Nothing
+ }
+ Nothing ->
{ model | timers <- Dict.update id (Maybe.map (updateTimer action)) model.timers }
RemoveTimer id ->
{ model | timers <- Dict.remove id model.timers }
@@ -71,7 +80,7 @@ update action model =
case model.timerEdition of
Just timerEdition ->
{ model
- | timers <- Dict.update timerEdition.id (Maybe.map (updateTimer (SetTime (toTime timerEdition.numbers)))) model.timers
+ | timers <- updateTimerTime timerEdition model.timers
, timerEdition <- Nothing
}
Nothing ->
@@ -81,5 +90,6 @@ update action model =
KeyPressed keyCode ->
{ model | timerEdition <- Maybe.map (updateTimerEdition (keyCodeToChar keyCode)) model.timerEdition }
-isEnter : KeyCode -> Bool
-isEnter = (==) 107
+updateTimerTime : TimerEdition -> Dict Id Timer -> Dict Id Timer
+updateTimerTime timerEdition =
+ Dict.update timerEdition.id (Maybe.map (updateTimer (SetTime (toTime timerEdition.numbers))))
diff --git a/src/Update/UpdateTimer.elm b/src/Update/UpdateTimer.elm
index e4671d9..c147d23 100644
--- a/src/Update/UpdateTimer.elm
+++ b/src/Update/UpdateTimer.elm
@@ -6,6 +6,7 @@ module Update.UpdateTimer
import Time (Time)
import Model.Timer (..)
+import Model.TimerState (..)
import Model.Id (..)
type TimerAction =
@@ -20,19 +21,22 @@ updateTimer action timer =
case action of
Restart ->
{ timer
- | isRunning <- True
- , currentTime <- initTime timer.initialTime
+ | currentTime <- initTime timer.initialTime
+ , state <- Running
}
Pause ->
+ { timer | state <- Idle }
+ ToggleRunning ->
{ timer
- | isRunning <- False
+ | state <-
+ if timer.currentTime > 0 && timer.state == Idle
+ then Running
+ else Idle
}
- ToggleRunning ->
- { timer | isRunning <- timer.currentTime > 0.0 && not timer.isRunning }
Stop ->
{ timer
- | isRunning <- False
- , currentTime <- initTime timer.initialTime
+ | currentTime <- initTime timer.initialTime
+ , state <- Idle
}
SetTime time ->
let augmentedTime = time + 999
diff --git a/src/View/Timer.elm b/src/View/Timer.elm
index b508dd6..2325d3a 100644
--- a/src/View/Timer.elm
+++ b/src/View/Timer.elm
@@ -13,6 +13,7 @@ import Maybe
import Model.Model (..)
import Model.Timer (..)
import Model.TimerEdition (..)
+import Model.TimerState (..)
import Model.Id (..)
import Update.Update (..)
@@ -25,49 +26,44 @@ import Utils.Maybe (..)
timerView : Model -> (Id, Timer) -> Html
timerView model (id, timer) =
div
- [ class <| "timer" ++ (if timer.isRunning then " isRunning" else "") ]
- [ button
- [ class "name block" ]
- [ text timer.name ]
- , let maybeEdition = filterMaybe (\te -> te.id == id) model.timerEdition
- in case maybeEdition of
- Just edition ->
- button
- [ class "time block edition"
- , onClick (Signal.send updates ValidTimerEdition)
- ]
- [ text (editionView edition.numbers) ]
- Nothing ->
- button
- [ class "time block"
- , onClick (Signal.send updates (EditTimer id))
- ]
- [ text (timeView timer.currentTime) ]
- , button
- [ class <| "restart block"
- , onClick (Signal.send updates (UpdateTimer id Restart))
- ]
- [ i [ class "fa fa-fw fa-backward" ] [] ]
- , button
- [ class <| "playPause block"
- , onClick (Signal.send updates (UpdateTimer id ToggleRunning))
- ]
- [ let icon = if timer.isRunning then "fa-pause" else "fa-play"
- in i
- [ class <| "fa fa-fw " ++ icon ]
- []
- ]
- , button
- [ class <| "stop block"
- , onClick (Signal.send updates (UpdateTimer id Stop))
- ]
- [ i [ class "fa fa-fw fa-stop" ] [] ]
- , button
- [ class <| "remove block"
- , onClick (Signal.send updates (RemoveTimer id))
- ]
- [ i [ class "fa fa-fw fa-remove" ] [] ]
+ [ [ (True, "timer")
+ , (timer.state == Running, "isRunning")
+ , (timer.state == Ringing, "isRinging")
+ ]
+ |> activatedClasses
]
+ [ nameBlock (id, timer)
+ , timeBlock model (id, timer)
+ , restartBlock (id, timer)
+ , playPauseBlock (id, timer)
+ , stopBlock (id, timer)
+ , removeBlock (id, timer)
+ ]
+
+nameBlock : (Id, Timer) -> Html
+nameBlock (id, timer) =
+ button
+ [ class "name block"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates NoOp))
+ ]
+ [ text timer.name ]
+
+timeBlock : Model -> (Id, Timer) -> Html
+timeBlock model (id, timer) =
+ let maybeEdition = filterMaybe (\te -> te.id == id) model.timerEdition
+ in case maybeEdition of
+ Just edition ->
+ button
+ [ class "time block edition"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates ValidTimerEdition))
+ ]
+ [ text (editionView edition.numbers) ]
+ Nothing ->
+ button
+ [ class "time block"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates (EditTimer id)))
+ ]
+ [ text (timeView timer.currentTime) ]
editionView : Numbers -> String
editionView numbers =
@@ -79,4 +75,46 @@ timeView time =
let totalSeconds = truncate (time / 1000)
totalMinutes = totalSeconds // 60
restSeconds = totalSeconds `rem` 60
- in (toString totalMinutes) ++ " : " ++ (String.padLeft 2 '0' (toString restSeconds))
+ in (String.padLeft 2 '0' (toString totalMinutes)) ++ " : " ++ (String.padLeft 2 '0' (toString restSeconds))
+
+restartBlock : (Id, Timer) -> Html
+restartBlock (id, timer) =
+ button
+ [ class <| "restart block"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates (UpdateTimer id Restart)))
+ ]
+ [ i [ class "fa fa-fw fa-backward" ] [] ]
+
+playPauseBlock : (Id, Timer) -> Html
+playPauseBlock (id, timer) =
+ button
+ [ class <| "playPause block"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates (UpdateTimer id ToggleRunning)))
+ ]
+ [ let icon = if timer.state == Running then "fa-pause" else "fa-play"
+ in i
+ [ class <| "fa fa-fw " ++ icon ]
+ []
+ ]
+
+stopBlock : (Id, Timer) -> Html
+stopBlock (id, timer) =
+ button
+ [ class <| "stop block"
+ , onClick (stopIfRinging (id, timer) (Signal.send updates (UpdateTimer id Stop)))
+ ]
+ [ i [ class "fa fa-fw fa-stop" ] [] ]
+
+removeBlock : (Id, Timer) -> Html
+removeBlock (id, timer) =
+ button
+ [ class <| "remove block"
+ , onClick (Signal.send updates (RemoveTimer id))
+ ]
+ [ i [ class "fa fa-fw fa-remove" ] [] ]
+
+stopIfRinging : (Id, Timer) -> Signal.Message -> Signal.Message
+stopIfRinging (id, timer) message =
+ if timer.state == Ringing
+ then Signal.send updates (UpdateTimer id Stop)
+ else message
diff --git a/src/View/View.elm b/src/View/View.elm
index d7a9b99..e86ea52 100644
--- a/src/View/View.elm
+++ b/src/View/View.elm
@@ -34,9 +34,15 @@ title : Html
title =
div
[ class "title" ]
- [ h1 [] [ text "Timer" ]
+ [ button
+ [ onClick (Signal.send updates Initialize)
+ , class "title"
+ ]
+ [ text "Timer" ]
, button
- [ onClick (Signal.send updates AddNewTimer) ]
+ [ onClick (Signal.send updates AddNewTimer)
+ , class "addTimer"
+ ]
[ i
[ class "fa fa-fw fa-plus" ]
[]