Support a FlashCard before showing the notes that comprise a chord
My much anticipated feature: first prompt the user for a name of a chord, then show the user that chord. Cascading changes: I changed the "Tap to practice" overlayButton's opacity from 30% to 100% because pausing when showFlashCard is True causes the two piece TIL: You can batch Elm Subscriptions using the Sub.batch function. What I haven't learned yet: How to best handle rotating screens for mobile devices (i.e. portrait vs. landscape modes). In time... What's left? - Support sound - Support a fine-tune section of the preferences - Support tablet and web browser variants - Ask users for the "I chord" instead of asking "C major Root position" - More styling (of course)
This commit is contained in:
parent
f92fe97aff
commit
d134db700f
5 changed files with 66 additions and 5 deletions
42
website/sandbox/learnpianochords/src/FlashCard.elm
Normal file
42
website/sandbox/learnpianochords/src/FlashCard.elm
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
module FlashCard exposing (render)
|
||||||
|
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (..)
|
||||||
|
import Responsive
|
||||||
|
import State
|
||||||
|
import Tailwind
|
||||||
|
import Theory
|
||||||
|
|
||||||
|
|
||||||
|
render :
|
||||||
|
{ chord : Theory.Chord
|
||||||
|
, visible : Bool
|
||||||
|
}
|
||||||
|
-> Html State.Msg
|
||||||
|
render { chord, visible } =
|
||||||
|
let
|
||||||
|
classes =
|
||||||
|
[ "bg-white"
|
||||||
|
, "fixed"
|
||||||
|
, "top-0"
|
||||||
|
, "left-0"
|
||||||
|
, "z-30"
|
||||||
|
, "w-screen"
|
||||||
|
, "h-screen"
|
||||||
|
, Tailwind.if_ visible "opacity-100" "opacity-0"
|
||||||
|
]
|
||||||
|
in
|
||||||
|
button
|
||||||
|
[ classes |> Tailwind.use |> class ]
|
||||||
|
[ h1
|
||||||
|
[ [ "text-center"
|
||||||
|
, "transform"
|
||||||
|
, "-rotate-90"
|
||||||
|
, Responsive.h1
|
||||||
|
]
|
||||||
|
|> Tailwind.use
|
||||||
|
|> class
|
||||||
|
]
|
||||||
|
[ text (Theory.viewChord chord) ]
|
||||||
|
]
|
|
@ -16,7 +16,10 @@ subscriptions model =
|
||||||
Sub.none
|
Sub.none
|
||||||
|
|
||||||
else
|
else
|
||||||
Time.every (model.tempo |> Misc.bpmToMilliseconds |> toFloat) (\_ -> State.NextChord)
|
Sub.batch
|
||||||
|
[ Time.every (model.tempo * 2 |> Misc.bpmToMilliseconds |> toFloat) (\_ -> State.ToggleFlashCard)
|
||||||
|
, Time.every (model.tempo |> Misc.bpmToMilliseconds |> toFloat) (\_ -> State.NextChord)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
view : State.Model -> Html State.Msg
|
view : State.Model -> Html State.Msg
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module Practice exposing (render)
|
module Practice exposing (render)
|
||||||
|
|
||||||
|
import FlashCard
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (..)
|
import Html.Events exposing (..)
|
||||||
|
@ -13,7 +14,7 @@ import UI
|
||||||
openPreferences : Html State.Msg
|
openPreferences : Html State.Msg
|
||||||
openPreferences =
|
openPreferences =
|
||||||
button
|
button
|
||||||
[ class "w-48 h-48 absolute left-0 top-0 z-40"
|
[ class "w-48 h-48 absolute left-0 top-0 z-50"
|
||||||
, onClick (State.SetView State.Preferences)
|
, onClick (State.SetView State.Preferences)
|
||||||
]
|
]
|
||||||
[ Icon.cog ]
|
[ Icon.cog ]
|
||||||
|
@ -36,6 +37,15 @@ render model =
|
||||||
, handleClick = handleClick
|
, handleClick = handleClick
|
||||||
, isVisible = model.isPaused
|
, isVisible = model.isPaused
|
||||||
}
|
}
|
||||||
|
, case model.selectedChord of
|
||||||
|
Just chord ->
|
||||||
|
FlashCard.render
|
||||||
|
{ chord = chord
|
||||||
|
, visible = model.showFlashCard
|
||||||
|
}
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
span [] []
|
||||||
, Piano.render
|
, Piano.render
|
||||||
{ chord = model.selectedChord
|
{ chord = model.selectedChord
|
||||||
, firstNote = model.firstNote
|
, firstNote = model.firstNote
|
||||||
|
|
|
@ -18,6 +18,7 @@ type Msg
|
||||||
| DoNothing
|
| DoNothing
|
||||||
| SetPracticeMode PracticeMode
|
| SetPracticeMode PracticeMode
|
||||||
| SetView View
|
| SetView View
|
||||||
|
| ToggleFlashCard
|
||||||
|
|
||||||
|
|
||||||
type View
|
type View
|
||||||
|
@ -46,6 +47,7 @@ type alias Model =
|
||||||
, lastNote : Theory.Note
|
, lastNote : Theory.Note
|
||||||
, practiceMode : PracticeMode
|
, practiceMode : PracticeMode
|
||||||
, view : View
|
, view : View
|
||||||
|
, showFlashCard : Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,10 +94,11 @@ init =
|
||||||
, whitelistedKeys = keys
|
, whitelistedKeys = keys
|
||||||
, selectedChord = Nothing
|
, selectedChord = Nothing
|
||||||
, isPaused = True
|
, isPaused = True
|
||||||
, tempo = 20
|
, tempo = 10
|
||||||
, firstNote = firstNote
|
, firstNote = firstNote
|
||||||
, lastNote = lastNote
|
, lastNote = lastNote
|
||||||
, view = Overview
|
, view = Overview
|
||||||
|
, showFlashCard = True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,3 +254,6 @@ update msg model =
|
||||||
}
|
}
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ToggleFlashCard ->
|
||||||
|
( { model | showFlashCard = not model.showFlashCard }, Cmd.none )
|
||||||
|
|
|
@ -132,7 +132,7 @@ overlayButton { label, handleClick, isVisible } =
|
||||||
, "top-0"
|
, "top-0"
|
||||||
, "left-0"
|
, "left-0"
|
||||||
, "block"
|
, "block"
|
||||||
, "z-30"
|
, "z-40"
|
||||||
, "w-screen"
|
, "w-screen"
|
||||||
, "h-screen"
|
, "h-screen"
|
||||||
, Tailwind.if_ isVisible "opacity-100" "opacity-0"
|
, Tailwind.if_ isVisible "opacity-100" "opacity-0"
|
||||||
|
@ -140,7 +140,7 @@ overlayButton { label, handleClick, isVisible } =
|
||||||
in
|
in
|
||||||
button
|
button
|
||||||
[ classes |> Tailwind.use |> class
|
[ classes |> Tailwind.use |> class
|
||||||
, style "background-color" "rgba(0,0,0,0.30)"
|
, style "background-color" "rgba(0,0,0,1.0)"
|
||||||
, onClick handleClick
|
, onClick handleClick
|
||||||
]
|
]
|
||||||
[ h1
|
[ h1
|
||||||
|
|
Loading…
Reference in a new issue