elm-twitch/src/Views.elm

198 lines
4.7 KiB
Elm

module Views exposing (view)
import Browser
import Colors
import Consts
import Core
import Element exposing (Element)
import Element.Background as Background
import Element.Border as Border
import Element.Font as Font
import Element.Input as Input
import Twitch
view : Core.FullModel -> Browser.Document Core.Msg
view model =
{ title = Consts.url
, body = [ Element.layout [] (viewContent model) ]
}
viewContent : Core.FullModel -> Element Core.Msg
viewContent model =
let
content =
case model of
Core.Unloaded ->
Element.none
Core.Loaded submodel ->
mainView submodel
in
Element.column [ Element.width Element.fill ] [ topBar, content ]
mainView : Core.Model -> Element Core.Msg
mainView model =
case model.page of
Core.Home ->
playlistsView model.playlists
topBar : Element Core.Msg
topBar =
Element.row
[ Element.width Element.fill
, Background.color Colors.primary
, Font.color Colors.white
, Font.size Consts.homeFontSize
]
[ homeButton ]
homeButton : Element Core.Msg
homeButton =
Input.button
[ Element.padding Consts.homePadding
, Element.height Element.fill
, Element.mouseOver [ Background.color Colors.primaryOver ]
, Font.bold
]
{ label = Element.text Consts.name
, onPress = Nothing
}
playlistsView : List Twitch.Playlist -> Element Core.Msg
playlistsView playlists =
let
empty =
Element.el [ Element.width Element.fill ] Element.none
views =
List.map playlistView playlists
grouped =
group 4 views
rows =
grouped
|> List.map (\x -> List.map (Maybe.withDefault empty) x)
|> List.map (Element.row [ Element.spacing 10, Element.width Element.fill ])
final =
Element.column [ Element.padding 10, Element.spacing 10, Element.width Element.fill ] rows
in
final
playlistView : Twitch.Playlist -> Element Core.Msg
playlistView playlist =
let
image =
Element.image [ Element.width Element.fill, Element.height Element.fill, Element.inFront inFront ]
{ description = "", src = Twitch.playlistMiniatureUrl playlist }
length =
List.length playlist.videos
label =
String.fromInt length
++ " video"
++ (if length > 1 then
"s"
else
""
)
inFront =
Element.el
[ Element.alignBottom
, Element.alignRight
, Background.color Colors.greyBackground
, Border.rounded 5
, Element.padding 5
, Font.color Colors.white
]
(Element.text label)
|> Element.el [ Element.alignBottom, Element.alignRight, Element.padding 5 ]
display =
Element.column [ Element.width Element.fill, Element.spacing 10 ]
[ image
, Element.paragraph [ Font.bold, Font.color Colors.blackFont ] [ Element.text playlist.name ]
]
button =
Input.button [ Element.width Element.fill, Element.alignTop ]
{ label = display
, onPress = Nothing
}
in
button
formatTime : Int -> String
formatTime time =
String.fromInt (toHours time)
++ ":"
++ String.fromInt (toMinutes time)
++ ":"
++ String.fromInt (toSeconds time)
toHours : Int -> Int
toHours i =
i // 3600
toMinutes : Int -> Int
toMinutes i =
modBy 3600 i // 60
toSeconds : Int -> Int
toSeconds i =
modBy 60 i
group : Int -> List a -> List (List (Maybe a))
group size list =
let
grouped =
List.map (List.map Just) (groupAux size list [])
groupedRev =
List.reverse grouped
( firstFixed, tail ) =
case groupedRev of
h :: t ->
( List.concat [ h, List.repeat (size - List.length h) Nothing ], t )
[] ->
( [], [] )
fixed =
(firstFixed :: tail) |> List.reverse
in
fixed
groupAux : Int -> List a -> List (List a) -> List (List a)
groupAux size list acc =
if List.isEmpty list then
acc
else
let
groupHead =
List.take size list
groupTail =
List.drop size list
in
groupAux size groupTail (groupHead :: acc)