From 2613aeeae0f4de44842ff0e796603d0316a61a14 Mon Sep 17 00:00:00 2001 From: Joris Guyonvarch Date: Wed, 18 Mar 2015 00:32:17 +0100 Subject: Can edit the time, unfortunately the enter key is overriden so the '+' key of the numpad is used instead --- src/Main.elm | 4 ++- src/Model/TimerEdition.elm | 56 ++++++++++++++++++++++++++++++++++++++- src/Update/Update.elm | 35 ++++++++++++++++++++++-- src/Update/UpdateTimer.elm | 18 +++++++++++-- src/Update/UpdateTimerEdition.elm | 20 ++++++++++++++ src/Utils/List.elm | 17 ++++++++++++ src/Utils/Maybe.elm | 13 +++++++++ src/View/Timer.elm | 37 ++++++++++++++------------ src/View/View.elm | 1 - 9 files changed, 177 insertions(+), 24 deletions(-) create mode 100644 src/Update/UpdateTimerEdition.elm create mode 100644 src/Utils/List.elm create mode 100644 src/Utils/Maybe.elm (limited to 'src') diff --git a/src/Main.elm b/src/Main.elm index c2a327b..42bcbc4 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -6,8 +6,9 @@ import Signal import Html (Html) import Time (..) import Mouse -import Debug import Json.Encode (Value) +import Keyboard +import Char import Model.Model (..) import Model.Position (..) @@ -26,6 +27,7 @@ input = [ Signal.subscribe updates , Signal.map DeltaTime (fps 30) , Signal.map (\_ -> ReadOnly) clickAway + , Signal.map KeyPressed Keyboard.lastPressed ] port clickPosition : Signal Value diff --git a/src/Model/TimerEdition.elm b/src/Model/TimerEdition.elm index c7b90c5..5feea33 100644 --- a/src/Model/TimerEdition.elm +++ b/src/Model/TimerEdition.elm @@ -1,16 +1,70 @@ module Model.TimerEdition ( TimerEdition + , Numbers , newTimerEdition + , keyCodeToChar + , toTime + , toMinutesAndSeconds ) where +import Time (Time) +import List +import Array +import String +import Keyboard (KeyCode) + import Model.Id (..) +import Utils.List (..) + type alias TimerEdition = { id : Id - , numbers : List Int + , numbers : Numbers } +type alias Numbers = List Char + newTimerEdition id = { id = id , numbers = [] } + +keyCodeToChar : KeyCode -> Maybe Char +keyCodeToChar code = + let zero = 96 + nine = zero + 9 + in if code >= zero && code <= nine + then ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] + |> Array.fromList + |> Array.get (code - zero) + else Nothing + +toTime : Numbers -> Time +toTime numbers = + numbers + |> toMinutesAndSeconds + |> \(a, b) -> (stringToInt a, stringToInt b) + |> \(minutes, seconds) -> (toFloat minutes) * 60 * 1000 + (toFloat seconds) * 1000 + +toMinutesAndSeconds : Numbers -> (String, String) +toMinutesAndSeconds numbers = + numbers + |> List.take 4 + |> List.reverse + |> completeBegin '0' 4 + |> splitAt 2 + |> \(a, b) -> (String.fromList a, String.fromList b) + +completeBegin : a -> Int -> List a -> List a +completeBegin x count xs = + let length = List.length xs + in List.append (repeat (count - length) x) xs + +stringToInt : String -> Int +stringToInt str = + str + |> String.toInt + |> \res -> + case res of + Ok n -> n + Err _ -> 0 diff --git a/src/Update/Update.elm b/src/Update/Update.elm index fa11921..4725970 100644 --- a/src/Update/Update.elm +++ b/src/Update/Update.elm @@ -8,6 +8,8 @@ import Signal import Dict import Time (Time) import Maybe +import Keyboard (KeyCode) +import Char import Model.Model (..) import Model.Timer (..) @@ -16,6 +18,7 @@ import Model.Id (..) import Model.IdGenerator (..) import Update.UpdateTimer (..) +import Update.UpdateTimerEdition (..) type Action = NoOp @@ -25,6 +28,7 @@ type Action = | RemoveTimer Id | EditTimer Id | ReadOnly + | KeyPressed KeyCode updates : Signal.Channel Action updates = Signal.channel NoOp @@ -46,10 +50,37 @@ update action model = , timers <- substractTimersTime delta model.timers } UpdateTimer id action -> - { model | timers <- Dict.update id (Maybe.map (updateTimer action)) model.timers } + let inEdition = + model.timerEdition + |> Maybe.map (\timerEdition -> timerEdition.id == id) + |> Maybe.withDefault False + in if inEdition + then + model + else + { model | timers <- Dict.update id (Maybe.map (updateTimer action)) model.timers } RemoveTimer id -> { model | timers <- Dict.remove id model.timers } EditTimer id -> - { model | timerEdition <- Just (newTimerEdition id) } + { model + | timerEdition <- Just (newTimerEdition id) + , timers <- Dict.update id (Maybe.map (updateTimer Pause)) model.timers + } ReadOnly -> { model | timerEdition <- Nothing } + KeyPressed keyCode -> + if isEnter keyCode + then + case model.timerEdition of + Just timerEdition -> + { model + | timers <- Dict.update timerEdition.id (Maybe.map (updateTimer (SetTime (toTime timerEdition.numbers)))) model.timers + , timerEdition <- Nothing + } + Nothing -> + { model | timerEdition <- Nothing } + else + { model | timerEdition <- Maybe.map (updateTimerEdition (keyCodeToChar keyCode)) model.timerEdition } + +isEnter : KeyCode -> Bool +isEnter = (==) 107 diff --git a/src/Update/UpdateTimer.elm b/src/Update/UpdateTimer.elm index 3eba549..e4671d9 100644 --- a/src/Update/UpdateTimer.elm +++ b/src/Update/UpdateTimer.elm @@ -3,26 +3,40 @@ module Update.UpdateTimer , updateTimer ) where +import Time (Time) + import Model.Timer (..) import Model.Id (..) type TimerAction = Restart + | Pause | ToggleRunning | Stop + | SetTime Time updateTimer : TimerAction -> Timer -> Timer updateTimer action timer = case action of - ToggleRunning -> - { timer | isRunning <- timer.currentTime > 0.0 && not timer.isRunning } Restart -> { timer | isRunning <- True , currentTime <- initTime timer.initialTime } + Pause -> + { timer + | isRunning <- False + } + ToggleRunning -> + { timer | isRunning <- timer.currentTime > 0.0 && not timer.isRunning } Stop -> { timer | isRunning <- False , currentTime <- initTime timer.initialTime } + SetTime time -> + let augmentedTime = time + 999 + in { timer + | initialTime <- augmentedTime + , currentTime <- augmentedTime + } diff --git a/src/Update/UpdateTimerEdition.elm b/src/Update/UpdateTimerEdition.elm new file mode 100644 index 0000000..da12ed0 --- /dev/null +++ b/src/Update/UpdateTimerEdition.elm @@ -0,0 +1,20 @@ +module Update.UpdateTimerEdition + ( updateTimerEdition + ) where + +import Char (..) +import Debug + +import Model.TimerEdition (..) + +updateTimerEdition : Maybe Char -> TimerEdition -> TimerEdition +updateTimerEdition maybeChar timerEdition = + case maybeChar of + Just char -> + if isDigit char + then + { timerEdition | numbers <- char :: timerEdition.numbers } + else + timerEdition + Nothing -> + timerEdition diff --git a/src/Utils/List.elm b/src/Utils/List.elm new file mode 100644 index 0000000..6895d83 --- /dev/null +++ b/src/Utils/List.elm @@ -0,0 +1,17 @@ +module Utils.List + ( repeat + , splitAt + ) where + +import List + +repeat : Int -> a -> List a +repeat count elem = + if count > 0 + then + elem :: (repeat (count - 1) elem) + else + [] + +splitAt : Int -> List a -> (List a, List a) +splitAt n xs = (List.take n xs, List.drop n xs) diff --git a/src/Utils/Maybe.elm b/src/Utils/Maybe.elm new file mode 100644 index 0000000..25d02e7 --- /dev/null +++ b/src/Utils/Maybe.elm @@ -0,0 +1,13 @@ +module Utils.Maybe + ( filterMaybe + ) where + +filterMaybe : (a -> Bool) -> Maybe a -> Maybe a +filterMaybe cond maybe = + case maybe of + Just x -> + if cond x + then Just x + else Nothing + Nothing -> + Nothing diff --git a/src/View/Timer.elm b/src/View/Timer.elm index 5ec5d02..5d98fd1 100644 --- a/src/View/Timer.elm +++ b/src/View/Timer.elm @@ -12,6 +12,7 @@ import Maybe import Model.Model (..) import Model.Timer (..) +import Model.TimerEdition (..) import Model.Id (..) import Update.Update (..) @@ -19,6 +20,8 @@ import Update.UpdateTimer (..) import View.ActivatedClasses (..) +import Utils.Maybe (..) + timerView : Model -> (Id, Timer) -> Html timerView model (id, timer) = div @@ -26,23 +29,18 @@ timerView model (id, timer) = [ button [ class "name block" ] [ text timer.name ] - , let inEdition = - model.timerEdition - |> Maybe.map (\te -> te.id == id) - |> Maybe.withDefault False - in button - ( [ [ (True, "time block") - , (inEdition, "edition") - ] - |> activatedClasses - ] - ++ if inEdition - then - [] - else - [ onClick (Signal.send updates (EditTimer id)) ] - ) - [ text (timeView timer.currentTime) ] + , let maybeEdition = filterMaybe (\te -> te.id == id) model.timerEdition + in case maybeEdition of + Just edition -> + button + [ class "time block edition" ] + [ 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)) @@ -69,6 +67,11 @@ timerView model (id, timer) = [ i [ class "fa fa-fw fa-remove" ] [] ] ] +editionView : Numbers -> String +editionView numbers = + let (minutes, seconds) = toMinutesAndSeconds numbers + in minutes ++ " : " ++ seconds + timeView : Time -> String timeView time = let totalSeconds = truncate (time / 1000) diff --git a/src/View/View.elm b/src/View/View.elm index 8da1316..d7a9b99 100644 --- a/src/View/View.elm +++ b/src/View/View.elm @@ -9,7 +9,6 @@ import Signal import List import Dict import Json.Decode as Json -import Debug import Model.Model (..) import Model.Timer (..) -- cgit v1.2.3