Browsing the pages work

This commit is contained in:
Thomas Forgione 2020-10-04 15:24:04 +02:00
parent 0215d94be9
commit 5872e50493
7 changed files with 202 additions and 49 deletions

View File

@ -15,7 +15,8 @@
"elm/time": "1.0.0", "elm/time": "1.0.0",
"elm/url": "1.0.0", "elm/url": "1.0.0",
"jims/html-parser": "1.0.0", "jims/html-parser": "1.0.0",
"mdgriffith/elm-ui": "1.1.8" "mdgriffith/elm-ui": "1.1.8",
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
}, },
"indirect": { "indirect": {
"elm/bytes": "1.0.8", "elm/bytes": "1.0.8",

View File

@ -1,4 +1,4 @@
module Colors exposing (blackFont, greyBackground, primary, primaryOver, white) module Colors exposing (blackFont, greyBackground, greyFont, primary, primaryOver, white)
import Element import Element
@ -26,3 +26,8 @@ greyBackground =
blackFont : Element.Color blackFont : Element.Color
blackFont = blackFont =
Element.rgb255 54 54 54 Element.rgb255 54 54 54
greyFont : Element.Color
greyFont =
Element.rgb255 128 128 128

View File

@ -1,4 +1,11 @@
module Consts exposing (homeFontSize, homePadding, name, url) module Consts exposing
( homeFontSize
, homePadding
, name
, normalFontSize
, titleFontSize
, url
)
url : String url : String
@ -11,6 +18,16 @@ name =
url url
normalFontSize : Int
normalFontSize =
13
titleFontSize : Int
titleFontSize =
15
homeFontSize : Int homeFontSize : Int
homeFontSize = homeFontSize =
25 25

View File

@ -3,6 +3,7 @@ module Core exposing (FullModel(..), Model, Msg(..), Page(..), init, update)
import Browser.Navigation import Browser.Navigation
import Json.Decode as Decode import Json.Decode as Decode
import Task import Task
import Time
import Twitch import Twitch
import Url import Url
@ -14,6 +15,7 @@ type FullModel
type alias Model = type alias Model =
{ playlists : List Twitch.Playlist { playlists : List Twitch.Playlist
, zone : Time.Zone
, page : Page , page : Page
} }
@ -26,7 +28,7 @@ type Page
type Msg type Msg
= Noop = Noop
| PlaylistsReceived (List Twitch.Playlist) | PlaylistsReceived ( List Twitch.Playlist, Time.Zone )
| HomeClicked | HomeClicked
| PlaylistClicked Twitch.Playlist | PlaylistClicked Twitch.Playlist
| VideoClicked Twitch.Playlist Twitch.Video | VideoClicked Twitch.Playlist Twitch.Video
@ -45,17 +47,17 @@ update msg model =
( Noop, _ ) -> ( Noop, _ ) ->
( model, Cmd.none ) ( model, Cmd.none )
( PlaylistsReceived playlists, _ ) -> ( PlaylistsReceived ( playlists, zone ), _ ) ->
( Loaded { playlists = playlists, page = Home }, Cmd.none ) ( Loaded { playlists = playlists, zone = zone, page = Home }, Cmd.none )
( HomeClicked, Loaded { playlists } ) -> ( HomeClicked, Loaded m ) ->
( Loaded { playlists = playlists, page = Home }, Cmd.none ) ( Loaded { m | page = Home }, Cmd.none )
( PlaylistClicked playlist, Loaded { playlists } ) -> ( PlaylistClicked playlist, Loaded m ) ->
( Loaded { playlists = playlists, page = Playlist playlist }, Cmd.none ) ( Loaded { m | page = Playlist playlist }, Cmd.none )
( VideoClicked playlist video, Loaded { playlists } ) -> ( VideoClicked playlist video, Loaded m ) ->
( Loaded { playlists = playlists, page = Video playlist video }, Cmd.none ) ( Loaded { m | page = Video playlist video }, Cmd.none )
_ -> _ ->
( model, Cmd.none ) ( model, Cmd.none )

52
src/TimeUtils.elm Normal file
View File

@ -0,0 +1,52 @@
module TimeUtils exposing (monthToString, pad2)
import Time
pad2 : String -> String
pad2 input =
if String.length input == 1 then
"0" ++ input
else
input
monthToString : Time.Month -> String
monthToString month =
case month of
Time.Jan ->
"01"
Time.Feb ->
"02"
Time.Mar ->
"03"
Time.Apr ->
"04"
Time.May ->
"05"
Time.Jun ->
"06"
Time.Jul ->
"07"
Time.Aug ->
"08"
Time.Sep ->
"09"
Time.Oct ->
"10"
Time.Nov ->
"11"
Time.Dec ->
"12"

View File

@ -8,8 +8,10 @@ module Twitch exposing
import Html.Parser import Html.Parser
import Http import Http
import Iso8601
import Json.Decode as Decode import Json.Decode as Decode
import Task exposing (Task) import Task exposing (Task)
import Time
type alias Playlist = type alias Playlist =
@ -23,6 +25,7 @@ type alias Video =
{ name : String { name : String
, url : String , url : String
, duration : Int , duration : Int
, date : Time.Posix
} }
@ -63,9 +66,17 @@ sortPlaylists playlists =
List.sortBy .url (List.map sortPlaylist playlists) |> List.reverse List.sortBy .url (List.map sortPlaylist playlists) |> List.reverse
fetchPlaylists : Task x (List Playlist) fetchPlaylists : Task x ( List Playlist, Time.Zone )
fetchPlaylists = fetchPlaylists =
fetchPlaylistPath |> Task.andThen fetchPlaylistsMapper |> Task.map sortPlaylists fetchPlaylistPath
|> Task.andThen fetchPlaylistsMapper
|> Task.map sortPlaylists
|> Task.andThen fetchTimezone
fetchTimezone : List Playlist -> Task x ( List Playlist, Time.Zone )
fetchTimezone playlists =
Task.map (\zone -> ( playlists, zone )) Time.here
fetchPlaylistPath : Task x (List String) fetchPlaylistPath : Task x (List String)
@ -129,10 +140,10 @@ parseVideo url result =
Ok v Ok v
_ -> _ ->
Ok { name = "", url = url, duration = 0 } Ok { name = "", url = url, duration = 0, date = Time.millisToPosix 0 }
_ -> _ ->
Ok { name = "", url = url, duration = 0 } Ok { name = "", url = url, duration = 0, date = Time.millisToPosix 0 }
fetchPlaylistsMapper : List String -> Task x (List Playlist) fetchPlaylistsMapper : List String -> Task x (List Playlist)
@ -221,6 +232,7 @@ decodePlaylistName =
decodeVideo : String -> Decode.Decoder Video decodeVideo : String -> Decode.Decoder Video
decodeVideo url = decodeVideo url =
Decode.map2 (\x y -> Video x url y) Decode.map3 (\x y -> Video x url y)
(Decode.field "title" Decode.string) (Decode.field "title" Decode.string)
(Decode.map Basics.round (Decode.field "duration" Decode.float)) (Decode.map Basics.round (Decode.field "duration" Decode.float))
(Decode.field "date" Iso8601.decoder)

View File

@ -9,13 +9,18 @@ import Element.Background as Background
import Element.Border as Border import Element.Border as Border
import Element.Font as Font import Element.Font as Font
import Element.Input as Input import Element.Input as Input
import Time
import TimeUtils
import Twitch import Twitch
view : Core.FullModel -> Browser.Document Core.Msg view : Core.FullModel -> Browser.Document Core.Msg
view model = view model =
{ title = Consts.url { title = Consts.url
, body = [ Element.layout [] (viewContent model) ] , body =
[ Element.layout [ Font.color Colors.blackFont, Font.size Consts.normalFontSize ]
(viewContent model)
]
} }
@ -40,10 +45,10 @@ mainView model =
playlistsView model.playlists playlistsView model.playlists
Core.Playlist playlist -> Core.Playlist playlist ->
videoMiniaturesView playlist videoMiniaturesView model.zone playlist
Core.Video playlist video -> Core.Video playlist video ->
videoView playlist video videoView model.zone playlist video
topBar : Element Core.Msg topBar : Element Core.Msg
@ -135,7 +140,7 @@ playlistView playlist =
Element.column [ Element.width Element.fill, Element.spacing 10 ] Element.column [ Element.width Element.fill, Element.spacing 10 ]
[ image [ image
, Element.paragraph , Element.paragraph
[ Font.bold, Font.color Colors.blackFont ] [ Font.bold, Font.size Consts.titleFontSize ]
[ Element.text playlist.name ] [ Element.text playlist.name ]
] ]
@ -148,14 +153,14 @@ playlistView playlist =
button button
videoMiniaturesView : Twitch.Playlist -> Element Core.Msg videoMiniaturesView : Time.Zone -> Twitch.Playlist -> Element Core.Msg
videoMiniaturesView playlist = videoMiniaturesView zone playlist =
let let
empty = empty =
Element.el [ Element.width Element.fill ] Element.none Element.el [ Element.width Element.fill ] Element.none
views = views =
List.map (videoMiniatureView playlist) playlist.videos List.map (videoMiniatureView zone playlist) playlist.videos
grouped = grouped =
group 4 views group 4 views
@ -171,20 +176,9 @@ videoMiniaturesView playlist =
final final
videoMiniatureView : Twitch.Playlist -> Twitch.Video -> Element Core.Msg videoMiniature : Twitch.Video -> Element Core.Msg
videoMiniatureView playlist video = videoMiniature video =
let let
image =
Element.image
[ Element.width Element.fill
, Element.height Element.fill
, Element.inFront inFront
]
{ description = "", src = Twitch.videoMiniatureUrl video }
label =
formatTime video.duration
inFront = inFront =
Element.text label Element.text label
|> Element.el |> Element.el
@ -199,12 +193,27 @@ videoMiniatureView playlist video =
, Element.padding 5 , Element.padding 5
] ]
image =
Element.image
[ Element.width Element.fill
, Element.height Element.fill
, Element.inFront inFront
]
{ description = "", src = Twitch.videoMiniatureUrl video }
label =
formatTime video.duration
in
image
videoMiniatureView : Time.Zone -> Twitch.Playlist -> Twitch.Video -> Element Core.Msg
videoMiniatureView zone playlist video =
let
display = display =
Element.column [ Element.width Element.fill, Element.spacing 10 ] Element.column [ Element.width Element.fill, Element.spacing 10 ]
[ image [ videoMiniature video
, Element.paragraph , videoDescription zone video
[ Font.bold, Font.color Colors.blackFont ]
[ Element.text video.name ]
] ]
button = button =
@ -216,17 +225,72 @@ videoMiniatureView playlist video =
button button
videoView : Twitch.Playlist -> Twitch.Video -> Element Core.Msg videoInList : Time.Zone -> Twitch.Video -> Element Core.Msg
videoView playlist video = videoInList zone video =
Element.row [ Element.padding 10, Element.width Element.fill, Element.spacing 20 ] Element.row [ Element.width Element.fill, Element.spacing 10 ]
[ Element.image [ Element.width (Element.fillPortion 2) ] [ Element.el [ Element.width (Element.fillPortion 1) ]
{ description = "", src = Twitch.videoMiniatureUrl video } (videoMiniature video)
, Element.column [ Element.alignTop, Element.width (Element.fillPortion 1) ] , Element.el [ Element.width (Element.fillPortion 2), Element.paddingXY 0 10, Element.alignTop ]
[ Element.text "sup" (videoDescription zone video)
]
] ]
videoView : Time.Zone -> Twitch.Playlist -> Twitch.Video -> Element Core.Msg
videoView zone playlist video =
Element.row [ Element.padding 10, Element.width Element.fill, Element.spacing 20 ]
[ Element.column [ Element.spacing 10, Element.width (Element.fillPortion 2) ]
[ Element.image [ Element.width Element.fill ]
{ description = "", src = Twitch.videoMiniatureUrl video }
, Element.paragraph
[ Font.size Consts.homeFontSize
, Font.bold
]
[ Element.text video.name ]
, Element.paragraph
[ Font.size Consts.titleFontSize ]
[ Element.text ("Diffusé le " ++ formatDate zone video.date) ]
]
, Element.column [ Element.alignTop, Element.spacing 10, Element.width (Element.fillPortion 1) ]
(List.map (videoInList zone) playlist.videos)
]
videoDescription : Time.Zone -> Twitch.Video -> Element Core.Msg
videoDescription zone video =
Element.column [ Element.spacing 10 ]
[ Element.paragraph
[ Font.bold
, Font.size Consts.titleFontSize
]
[ Element.text video.name ]
, Element.paragraph
[ Font.color Colors.greyFont
]
[ Element.text ("Diffusé le " ++ formatDate zone video.date) ]
]
formatDate : Time.Zone -> Time.Posix -> String
formatDate zone time =
let
day =
Time.toDay zone time |> String.fromInt |> TimeUtils.pad2
month =
Time.toMonth zone time |> TimeUtils.monthToString
year =
Time.toYear zone time |> String.fromInt |> TimeUtils.pad2
hours =
Time.toHour zone time |> String.fromInt
minutes =
Time.toMinute zone time |> String.fromInt |> TimeUtils.pad2
in
day ++ "/" ++ month ++ "/" ++ year ++ " à " ++ hours ++ "h" ++ minutes
formatTime : Int -> String formatTime : Int -> String
formatTime time = formatTime time =
let let