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)