Remove DOM, adds support for thumbnails
This commit is contained in:
parent
b4705905e1
commit
638faccdb0
1
elm.json
1
elm.json
|
@ -6,7 +6,6 @@
|
||||||
"elm-version": "0.19.1",
|
"elm-version": "0.19.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"direct": {
|
"direct": {
|
||||||
"K-Adam/elm-dom": "1.0.0",
|
|
||||||
"andrewMacmurray/elm-simple-animation": "2.1.0",
|
"andrewMacmurray/elm-simple-animation": "2.1.0",
|
||||||
"elm/browser": "1.0.2",
|
"elm/browser": "1.0.2",
|
||||||
"elm/core": "1.0.5",
|
"elm/core": "1.0.5",
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module Events exposing (player, seekBar, subs, video)
|
module Events exposing (player, seekBar, subs, video)
|
||||||
|
|
||||||
import Browser.Events
|
import Browser.Events
|
||||||
import DOM as Dom
|
|
||||||
import Element
|
import Element
|
||||||
import Html
|
import Html
|
||||||
import Html.Attributes
|
import Html.Attributes
|
||||||
|
@ -73,26 +72,29 @@ seekBar : Video -> List (Element.Attribute Video.Msg)
|
||||||
seekBar model =
|
seekBar model =
|
||||||
List.map Element.htmlAttribute
|
List.map Element.htmlAttribute
|
||||||
[ Html.Events.on "click" (decodeSeek model)
|
[ Html.Events.on "click" (decodeSeek model)
|
||||||
|
, Html.Events.on "mouseenter" decodeMouseEnter
|
||||||
|
, Html.Events.on "mouseleave" decodeMouseLeave
|
||||||
|
, Html.Events.on "mousemove" decodeMouseEnter
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
decodeDurationChanged : Decode.Decoder Video.Msg
|
decodeDurationChanged : Decode.Decoder Video.Msg
|
||||||
decodeDurationChanged =
|
decodeDurationChanged =
|
||||||
Dom.target <|
|
Decode.field "target" <|
|
||||||
Decode.map Video.NowHasDuration
|
Decode.map Video.NowHasDuration
|
||||||
(Decode.field "duration" Decode.float)
|
(Decode.field "duration" Decode.float)
|
||||||
|
|
||||||
|
|
||||||
decodePosition : Decode.Decoder Video.Msg
|
decodePosition : Decode.Decoder Video.Msg
|
||||||
decodePosition =
|
decodePosition =
|
||||||
Dom.target <|
|
Decode.field "target" <|
|
||||||
Decode.map Video.NowAtPosition
|
Decode.map Video.NowAtPosition
|
||||||
(Decode.field "currentTime" Decode.float)
|
(Decode.field "currentTime" Decode.float)
|
||||||
|
|
||||||
|
|
||||||
decodeVolumeChange : Decode.Decoder Video.Msg
|
decodeVolumeChange : Decode.Decoder Video.Msg
|
||||||
decodeVolumeChange =
|
decodeVolumeChange =
|
||||||
Dom.target <|
|
Decode.field "target" <|
|
||||||
Decode.map2 Video.NowAtVolume
|
Decode.map2 Video.NowAtVolume
|
||||||
(Decode.field "volume" Decode.float)
|
(Decode.field "volume" Decode.float)
|
||||||
(Decode.field "muted" Decode.bool)
|
(Decode.field "muted" Decode.bool)
|
||||||
|
@ -102,15 +104,15 @@ decodeSeek : Video -> Decode.Decoder Video.Msg
|
||||||
decodeSeek model =
|
decodeSeek model =
|
||||||
Decode.map2 (\x y -> Video.Seek (toFloat x / toFloat y * model.duration))
|
Decode.map2 (\x y -> Video.Seek (toFloat x / toFloat y * model.duration))
|
||||||
(Decode.field "layerX" Decode.int)
|
(Decode.field "layerX" Decode.int)
|
||||||
(Dom.target <| Decode.field "offsetWidth" Decode.int)
|
(Decode.field "target" <| Decode.field "offsetWidth" Decode.int)
|
||||||
|
|
||||||
|
|
||||||
decodeProgress : Decode.Decoder Video.Msg
|
decodeProgress : Decode.Decoder Video.Msg
|
||||||
decodeProgress =
|
decodeProgress =
|
||||||
decodeTimeRanges
|
decodeTimeRanges
|
||||||
|> Decode.field "asArray"
|
|> Decode.field "polymnyVideoAsArray"
|
||||||
|> Decode.field "buffered"
|
|> Decode.field "buffered"
|
||||||
|> Dom.target
|
|> Decode.field "target"
|
||||||
|> Decode.map Video.NowLoaded
|
|> Decode.map Video.NowLoaded
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,14 +133,14 @@ decodeFullscreenChange =
|
||||||
Decode.value
|
Decode.value
|
||||||
|> Decode.nullable
|
|> Decode.nullable
|
||||||
|> Decode.field "fullscreenElement"
|
|> Decode.field "fullscreenElement"
|
||||||
|> Decode.field "document"
|
|> Decode.field "polymnyVideoDocument"
|
||||||
|> Dom.target
|
|> Decode.field "target"
|
||||||
|> Decode.map (\x -> Video.NowIsFullscreen (x /= Nothing))
|
|> Decode.map (\x -> Video.NowIsFullscreen (x /= Nothing))
|
||||||
|
|
||||||
|
|
||||||
decodeVideoResize : Decode.Decoder Video.Msg
|
decodeVideoResize : Decode.Decoder Video.Msg
|
||||||
decodeVideoResize =
|
decodeVideoResize =
|
||||||
Dom.target <|
|
Decode.field "target" <|
|
||||||
Decode.map2 (\x y -> Video.NowHasSize ( x, y ))
|
Decode.map2 (\x y -> Video.NowHasSize ( x, y ))
|
||||||
(Decode.field "videoWidth" Decode.int)
|
(Decode.field "videoWidth" Decode.int)
|
||||||
(Decode.field "videoHeight" Decode.int)
|
(Decode.field "videoHeight" Decode.int)
|
||||||
|
@ -146,11 +148,23 @@ decodeVideoResize =
|
||||||
|
|
||||||
decodePlaybackRateChange : Decode.Decoder Video.Msg
|
decodePlaybackRateChange : Decode.Decoder Video.Msg
|
||||||
decodePlaybackRateChange =
|
decodePlaybackRateChange =
|
||||||
Dom.target <|
|
Decode.field "target" <|
|
||||||
Decode.map Video.NowHasPlaybackRate
|
Decode.map Video.NowHasPlaybackRate
|
||||||
(Decode.field "playbackRate" Decode.float)
|
(Decode.field "playbackRate" Decode.float)
|
||||||
|
|
||||||
|
|
||||||
|
decodeMouseEnter : Decode.Decoder Video.Msg
|
||||||
|
decodeMouseEnter =
|
||||||
|
Decode.map2 (\x y -> Video.NowHasMiniature (Just ( x, y )))
|
||||||
|
(Decode.field "offsetX" Decode.int)
|
||||||
|
(Decode.field "target" <| Decode.field "offsetWidth" Decode.int)
|
||||||
|
|
||||||
|
|
||||||
|
decodeMouseLeave : Decode.Decoder Video.Msg
|
||||||
|
decodeMouseLeave =
|
||||||
|
Decode.succeed (Video.NowHasMiniature Nothing)
|
||||||
|
|
||||||
|
|
||||||
decodeKeyDown : Video -> Decode.Decoder Video.Msg
|
decodeKeyDown : Video -> Decode.Decoder Video.Msg
|
||||||
decodeKeyDown model =
|
decodeKeyDown model =
|
||||||
Decode.field "keyCode" Decode.int
|
Decode.field "keyCode" Decode.int
|
||||||
|
|
|
@ -2,7 +2,6 @@ module Main exposing (..)
|
||||||
|
|
||||||
import Browser
|
import Browser
|
||||||
import Browser.Events
|
import Browser.Events
|
||||||
import DOM as Dom
|
|
||||||
import Element exposing (Element)
|
import Element exposing (Element)
|
||||||
import Element.Background as Background
|
import Element.Background as Background
|
||||||
import Element.Border as Border
|
import Element.Border as Border
|
||||||
|
|
|
@ -35,6 +35,7 @@ type alias Video =
|
||||||
, showSettings : Bool
|
, showSettings : Bool
|
||||||
, subtitles : List SubtitleTrack
|
, subtitles : List SubtitleTrack
|
||||||
, subtitleTrack : Maybe SubtitleTrack
|
, subtitleTrack : Maybe SubtitleTrack
|
||||||
|
, showMiniature : Maybe ( Int, Int )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ fromUrl url =
|
||||||
, showSettings = False
|
, showSettings = False
|
||||||
, subtitles = []
|
, subtitles = []
|
||||||
, subtitleTrack = Nothing
|
, subtitleTrack = Nothing
|
||||||
|
, showMiniature = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,6 +107,7 @@ type Msg
|
||||||
| NowHasPlaybackRate Float
|
| NowHasPlaybackRate Float
|
||||||
| NowHasSubtitles (List SubtitleTrack)
|
| NowHasSubtitles (List SubtitleTrack)
|
||||||
| NowHasSubtitleTrack (Maybe SubtitleTrack)
|
| NowHasSubtitleTrack (Maybe SubtitleTrack)
|
||||||
|
| NowHasMiniature (Maybe ( Int, Int ))
|
||||||
|
|
||||||
|
|
||||||
update : Msg -> Video -> ( Video, Cmd Msg )
|
update : Msg -> Video -> ( Video, Cmd Msg )
|
||||||
|
@ -192,6 +195,9 @@ update msg model =
|
||||||
NowHasSubtitleTrack track ->
|
NowHasSubtitleTrack track ->
|
||||||
( { model | subtitleTrack = track }, Cmd.none )
|
( { model | subtitleTrack = track }, Cmd.none )
|
||||||
|
|
||||||
|
NowHasMiniature miniature ->
|
||||||
|
( { model | showMiniature = miniature }, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
port polymnyVideoInit : String -> Cmd msg
|
port polymnyVideoInit : String -> Cmd msg
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,60 @@ embed screenSize model =
|
||||||
)
|
)
|
||||||
Element.none
|
Element.none
|
||||||
)
|
)
|
||||||
|
, Element.above
|
||||||
|
(case model.showMiniature of
|
||||||
|
Just ( position, size ) ->
|
||||||
|
let
|
||||||
|
relativePosition =
|
||||||
|
toFloat position / toFloat size
|
||||||
|
|
||||||
|
percentage =
|
||||||
|
String.fromFloat (relativePosition * 100) ++ "%"
|
||||||
|
|
||||||
|
miniatureId =
|
||||||
|
round (relativePosition * 100)
|
||||||
|
|
||||||
|
miniatureIdString =
|
||||||
|
"miniature-" ++ String.padLeft 3 '0' (String.fromInt miniatureId) ++ ".png"
|
||||||
|
|
||||||
|
miniatureUrl =
|
||||||
|
model.url
|
||||||
|
|> String.split "/"
|
||||||
|
|> List.reverse
|
||||||
|
|> List.drop 1
|
||||||
|
|> (\list -> miniatureIdString :: list)
|
||||||
|
|> List.reverse
|
||||||
|
|> String.join "/"
|
||||||
|
|
||||||
|
rightPosition =
|
||||||
|
(position - 180 - 6)
|
||||||
|
|> max 0
|
||||||
|
|> min (size - 360 - 28)
|
||||||
|
|> toFloat
|
||||||
|
in
|
||||||
|
Element.column
|
||||||
|
[ Element.moveRight rightPosition
|
||||||
|
, Element.spacing 10
|
||||||
|
]
|
||||||
|
[ Element.image
|
||||||
|
[ Border.color (Element.rgb 1 1 1)
|
||||||
|
, Border.width 2
|
||||||
|
]
|
||||||
|
{ src = miniatureUrl, description = "miniature" }
|
||||||
|
, Element.el
|
||||||
|
[ Element.centerX
|
||||||
|
, Font.shadow
|
||||||
|
{ offset = ( 0, 0 )
|
||||||
|
, blur = 4
|
||||||
|
, color = Element.rgb 0 0 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
(Element.text (formatTime (relativePosition * model.duration)))
|
||||||
|
]
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Element.none
|
||||||
|
)
|
||||||
]
|
]
|
||||||
[ Element.el
|
[ Element.el
|
||||||
[ Background.color (Element.rgba 1 0 0 0.75)
|
[ Background.color (Element.rgba 1 0 0 0.75)
|
||||||
|
|
Loading…
Reference in New Issue