Basic sound controls ° keybaord shortcuts

This commit is contained in:
Thomas Forgione 2021-06-14 10:46:34 +02:00
parent e99a5ed1e3
commit 37a8253387
3 changed files with 137 additions and 10 deletions

View File

@ -79,6 +79,7 @@
app.ports.seek.subscribe(function(arg) {
const video = document.getElementById('video');
console.log(arg);
video.currentTime = arg;
});
@ -113,6 +114,12 @@
});
}
});
app.ports.setVolume.subscribe(function(arg) {
const video = document.getElementById('video');
video.volume = arg.volume;
video.muted = arg.muted;
});
</script>
</body>
</html>

View File

@ -78,3 +78,35 @@ check =
svgFeatherIcon "check"
[ Svg.polyline [ points "20 6 9 17 4 12" ] []
]
volume : Bool -> Element msg
volume =
svgFeatherIcon "volume"
[ Svg.polygon [ points "11 5 6 9 2 9 2 15 6 15 11 19 11 5" ] []
]
volume1 : Bool -> Element msg
volume1 =
svgFeatherIcon "volume-1"
[ Svg.polygon [ points "11 5 6 9 2 9 2 15 6 15 11 19 11 5" ] []
, Svg.path [ d "M15.54 8.46a5 5 0 0 1 0 7.07" ] []
]
volume2 : Bool -> Element msg
volume2 =
svgFeatherIcon "volume-2"
[ Svg.polygon [ points "11 5 6 9 2 9 2 15 6 15 11 19 11 5" ] []
, Svg.path [ d "M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07" ] []
]
volumeX : Bool -> Element msg
volumeX =
svgFeatherIcon "volume-x"
[ Svg.polygon [ points "11 5 6 9 2 9 2 15 6 15 11 19 11 5" ] []
, Svg.line [ x1 "23", y1 "9", x2 "17", y2 "15" ] []
, Svg.line [ x1 "17", y1 "9", x2 "23", y2 "15" ] []
]

View File

@ -26,7 +26,7 @@ main =
, update = update
, view = view
, subscriptions =
\_ ->
\model ->
Sub.batch
[ nowHasQualities NowHasQualities
, nowHasQuality
@ -40,6 +40,7 @@ main =
)
, Browser.Events.onAnimationFrameDelta AnimationFrameDelta
, Browser.Events.onResize (\x y -> NowHasWindowSize ( x, y ))
, Browser.Events.onKeyDown (decodeKeyDown model)
]
, onUrlChange = \_ -> Noop
, onUrlRequest = \_ -> Noop
@ -81,6 +82,7 @@ type Msg
| SetSettings Settings
| SetPlaybackRate Float
| SetQuality Quality.Quality
| SetVolume Float Bool
| RequestFullscreen
| ExitFullscreen
| AnimationFrameDelta Float
@ -145,8 +147,8 @@ update msg model =
PlayPause ->
( model, playPause () )
Seek ratio ->
( model, seek (ratio * model.duration) )
Seek time ->
( model, seek time )
SetPlaybackRate rate ->
( { model | showSettings = False, settings = All }, setPlaybackRate rate )
@ -166,6 +168,9 @@ update msg model =
SetQuality q ->
( { model | showSettings = False, settings = All }, setQuality q )
SetVolume v m ->
( model, setVolume { volume = v, muted = m } )
AnimationFrameDelta delta ->
if model.animationFrame + delta > 3500 then
( { model | animationFrame = model.animationFrame + delta, showSettings = False, settings = All }, Cmd.none )
@ -301,7 +306,7 @@ video model =
(Element.width Element.fill
:: Element.height Element.fill
:: Element.pointer
:: seekBarEvents
:: seekBarEvents model
)
Element.none
)
@ -320,6 +325,7 @@ video model =
, Element.row
[ Element.spacing 10, Element.width Element.fill ]
[ playPauseButton model.playing
, volumeButton model.volume model.muted
, Element.el [ Element.moveDown 2.5 ] (Element.text (formatTime model.position ++ " / " ++ formatTime model.duration))
, Element.row [ Element.spacing 10, Element.alignRight ]
[ settingsButton, fullscreenButton model.isFullscreen ]
@ -534,6 +540,28 @@ fullscreenButton isFullscreen =
)
volumeButton : Float -> Bool -> Element Msg
volumeButton volume muted =
let
icon =
if muted then
Icons.volumeX
else if volume < 0.3 then
Icons.volume
else if volume < 0.6 then
Icons.volume1
else
Icons.volume2
in
Input.button []
{ label = icon True
, onPress = Just (SetVolume volume (not muted))
}
settingsButton : Element Msg
settingsButton =
Input.button []
@ -564,10 +592,10 @@ videoEvents =
]
seekBarEvents : List (Element.Attribute Msg)
seekBarEvents =
seekBarEvents : Model -> List (Element.Attribute Msg)
seekBarEvents model =
List.map Element.htmlAttribute
[ Html.Events.on "click" decodeSeek
[ Html.Events.on "click" (decodeSeek model)
]
@ -593,9 +621,9 @@ decodeVolumeChange =
(Decode.field "muted" Decode.bool)
decodeSeek : Decode.Decoder Msg
decodeSeek =
Decode.map2 (\x y -> Seek (toFloat x / toFloat y))
decodeSeek : Model -> Decode.Decoder Msg
decodeSeek model =
Decode.map2 (\x y -> Seek (toFloat x / toFloat y * model.duration))
(Decode.field "layerX" Decode.int)
(Dom.target <| Decode.field "offsetWidth" Decode.int)
@ -646,6 +674,63 @@ decodePlaybackRateChange =
(Decode.field "playbackRate" Decode.float)
decodeKeyDown : Model -> Decode.Decoder Msg
decodeKeyDown model =
Decode.field "keyCode" Decode.int
|> Decode.andThen
(\x ->
case x of
-- Enter key
32 ->
Decode.succeed PlayPause
-- J key
74 ->
Decode.succeed (Seek (max 0 (model.position - 10)))
-- L key
76 ->
Decode.succeed (Seek (min model.duration (model.position + 10)))
-- K key
75 ->
Decode.succeed PlayPause
-- Left arrow
37 ->
Decode.succeed (Seek (max 0 (model.position - 5)))
-- Right arrow
39 ->
Decode.succeed (Seek (min model.duration (model.position + 5)))
-- Down arrow
40 ->
Decode.succeed (SetVolume (max 0 (model.volume - 0.1)) model.muted)
-- Top arrow
38 ->
Decode.succeed (SetVolume (min 1 (model.volume + 0.1)) model.muted)
-- M key
77 ->
Decode.succeed (SetVolume model.volume (not model.muted))
-- F key
70 ->
Decode.succeed
(if model.isFullscreen then
ExitFullscreen
else
RequestFullscreen
)
_ ->
Decode.fail ("no shortcut for code " ++ String.fromInt x)
)
every : Float -> List ( Float, Float ) -> List ( Float, Float, Bool )
every duration input =
everyAux duration 0.0 [] input |> List.reverse |> List.filter (\( x, y, _ ) -> x /= y)
@ -724,6 +809,9 @@ port setPlaybackRate : Float -> Cmd msg
port setQuality : Quality.Quality -> Cmd msg
port setVolume : { volume : Float, muted : Bool } -> Cmd msg
port nowHasQualities : (List Int -> msg) -> Sub msg