This commit is contained in:
Thomas Forgione 2020-11-06 11:43:28 +01:00
parent 5b902ec915
commit cace6f09f8
3 changed files with 103 additions and 125 deletions

View File

@ -1,4 +1,4 @@
module Core exposing (FullModel(..), Model, Msg(..), Page(..), init, subscriptions, update) module Core exposing (Model, Msg(..), Page(..), init, subscriptions, update)
import Browser import Browser
import Browser.Events as Events import Browser.Events as Events
@ -15,11 +15,6 @@ import Twitch
import Url import Url
type FullModel
= Unloaded Element.Device Url.Url Nav.Key Time.Zone
| Loaded Model
type alias Model = type alias Model =
{ playlists : List Twitch.Playlist { playlists : List Twitch.Playlist
, zone : Time.Zone , zone : Time.Zone
@ -27,6 +22,7 @@ type alias Model =
, key : Nav.Key , key : Nav.Key
, device : Element.Device , device : Element.Device
, time : Time.Posix , time : Time.Posix
, url : Url.Url
} }
@ -53,9 +49,9 @@ type Msg
| TimeReceived Time.Posix | TimeReceived Time.Posix
init : { width : Int, height : Int } -> Url.Url -> Nav.Key -> ( FullModel, Cmd Msg ) init : { width : Int, height : Int } -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init { width, height } url key = init { width, height } url key =
( Unloaded (Element.classifyDevice { width = width, height = height }) url key Time.utc ( Model [] Time.utc (Home Nothing) key (Element.classifyDevice { width = width, height = height }) (Time.millisToPosix 0) url
, Cmd.batch , Cmd.batch
[ Task.attempt TimeZoneReceivedResult TimeZone.getZone [ Task.attempt TimeZoneReceivedResult TimeZone.getZone
, Twitch.fetchPlaylists resultToMsg , Twitch.fetchPlaylists resultToMsg
@ -73,7 +69,7 @@ resultToMsg result =
Noop Noop
subscriptions : FullModel -> Sub Msg subscriptions : Model -> Sub Msg
subscriptions _ = subscriptions _ =
Sub.batch Sub.batch
[ Events.onResize (\w h -> SizeReceived w h) [ Events.onResize (\w h -> SizeReceived w h)
@ -81,166 +77,156 @@ subscriptions _ =
] ]
update : Msg -> FullModel -> ( FullModel, Cmd Msg ) update : Msg -> Model -> ( Model, Cmd Msg )
update msg model = update msg model =
case ( msg, model ) of case ( msg, model ) of
( Noop, _ ) -> ( Noop, _ ) ->
( model, Cmd.none ) ( model, Cmd.none )
( TimeZoneReceived z, Unloaded d u k _ ) -> ( TimeZoneReceived z, m ) ->
( Unloaded d u k z, Cmd.none ) ( { m | zone = z }, Cmd.none )
( TimeZoneReceived z, Loaded m ) -> ( TimeZoneReceivedResult (Ok ( _, zone )), m ) ->
( Loaded { m | zone = z }, Cmd.none ) ( { m | zone = zone }, Cmd.none )
( TimeZoneReceivedResult (Ok ( _, zone )), Unloaded d u k _ ) ->
( Unloaded d u k zone, Cmd.none )
( TimeZoneReceivedResult (Ok ( _, zone )), Loaded m ) ->
( Loaded { m | zone = zone }, Cmd.none )
( TimeZoneReceivedResult (Err _), _ ) -> ( TimeZoneReceivedResult (Err _), _ ) ->
( model, Task.perform TimeZoneReceived Time.here ) ( model, Task.perform TimeZoneReceived Time.here )
( TimeReceived p, Loaded m ) -> ( TimeReceived p, m ) ->
( Loaded { m | time = p }, Cmd.none ) ( { m | time = p }, Cmd.none )
( HoverPlaylist hover, Loaded m ) -> ( HoverPlaylist hover, m ) ->
case m.page of case m.page of
Home Nothing -> Home Nothing ->
( Loaded { m | page = Home (Just (Hover.hover hover m.time)) }, Cmd.none ) ( { m | page = Home (Just (Hover.hover hover m.time)) }, Cmd.none )
_ -> _ ->
( Loaded m, Cmd.none ) ( m, Cmd.none )
( HoverVideo hover, Loaded m ) -> ( HoverVideo hover, m ) ->
case m.page of case m.page of
Playlist p Nothing -> Playlist p Nothing ->
( Loaded { m | page = Playlist p (Just (Hover.hover hover m.time)) }, Cmd.none ) ( { m | page = Playlist p (Just (Hover.hover hover m.time)) }, Cmd.none )
Video p v Nothing -> Video p v Nothing ->
( Loaded { m | page = Video p v (Just (Hover.hover v m.time)) }, Cmd.none ) ( { m | page = Video p v (Just (Hover.hover v m.time)) }, Cmd.none )
_ -> _ ->
( Loaded m, Cmd.none ) ( m, Cmd.none )
( Unhover, Loaded m ) -> ( Unhover, m ) ->
case m.page of case m.page of
Home _ -> Home _ ->
( Loaded { m | page = Home Nothing }, Cmd.none ) ( { m | page = Home Nothing }, Cmd.none )
Playlist p _ -> Playlist p _ ->
( Loaded { m | page = Playlist p Nothing }, Cmd.none ) ( { m | page = Playlist p Nothing }, Cmd.none )
Video p v _ -> Video p v _ ->
( Loaded { m | page = Video p v Nothing }, Cmd.none ) ( { m | page = Video p v Nothing }, Cmd.none )
( SizeReceived w h, Loaded m ) -> ( SizeReceived w h, m ) ->
( Loaded { m | device = Element.classifyDevice { width = w, height = h } } ( { m | device = Element.classifyDevice { width = w, height = h } }
, Cmd.none , Cmd.none
) )
( PlaylistsReceived playlists, Unloaded device url key zone ) -> ( PlaylistsReceived playlists, m ) ->
update update
(UrlReceived url) (UrlReceived m.url)
(Loaded { m | playlists = playlists, page = Home Nothing }
{ key = key
, playlists = playlists
, zone = zone
, page = Home Nothing
, device = device
, time = Time.millisToPosix 0
}
)
( HomeClicked, Loaded m ) -> ( HomeClicked, m ) ->
( model ( model
, Nav.pushUrl m.key "#" , Nav.pushUrl m.key "#"
) )
( PlaylistClicked playlist, Loaded m ) -> ( PlaylistClicked playlist, m ) ->
( model ( model
, Nav.pushUrl m.key ("#" ++ playlist.url) , Nav.pushUrl m.key ("#" ++ playlist.url)
) )
( VideoClicked playlist video, Loaded m ) -> ( VideoClicked playlist video, m ) ->
( model ( model
, Nav.pushUrl m.key ("#" ++ playlist.url ++ video.url) , Nav.pushUrl m.key ("#" ++ playlist.url ++ video.url)
) )
( UrlReceived url, Loaded m ) -> ( UrlReceived url, m ) ->
let if List.isEmpty m.playlists then
splits = ( { m | url = url }, Cmd.none )
String.split "?" (Maybe.withDefault "" url.fragment)
( split, args ) = else
case splits of let
h1 :: h2 :: _ -> splits =
( String.split "/" h1, parseQueryString h2 ) String.split "?" (Maybe.withDefault "" url.fragment)
h1 :: _ -> ( split, args ) =
( String.split "/" h1, Dict.empty ) case splits of
h1 :: h2 :: _ ->
( String.split "/" h1, parseQueryString h2 )
_ -> h1 :: _ ->
( [], Dict.empty ) ( String.split "/" h1, Dict.empty )
time = _ ->
case Dict.get "t" args of ( [], Dict.empty )
Just "0" ->
Nothing
Just t -> time =
Just t case Dict.get "t" args of
Just "0" ->
Nothing
_ -> Just t ->
Nothing Just t
( playlistName, videoName ) = _ ->
case split of Nothing
p :: v :: _ ->
( Just (p ++ "/"), Just (v ++ "/") )
p :: _ -> ( playlistName, videoName ) =
( Just (p ++ "/"), Nothing ) case split of
p :: v :: _ ->
( Just (p ++ "/"), Just (v ++ "/") )
_ -> p :: _ ->
( Nothing, Nothing ) ( Just (p ++ "/"), Nothing )
playlist = _ ->
List.head (List.filter (\x -> Just x.url == playlistName) m.playlists) ( Nothing, Nothing )
video = playlist =
case playlist of List.head (List.filter (\x -> Just x.url == playlistName) m.playlists)
Just p ->
List.head (List.filter (\x -> Just x.url == videoName) p.videos)
_ -> video =
Nothing case playlist of
Just p ->
List.head (List.filter (\x -> Just x.url == videoName) p.videos)
( page, cmd ) = _ ->
case ( playlist, video ) of Nothing
( Just p, Just v ) ->
( Video p v Nothing
, Ports.registerVideo ( Twitch.videoId v, "videos/" ++ p.url ++ v.url, time )
)
( Just p, Nothing ) -> ( page, cmd ) =
( Playlist p Nothing, Cmd.none ) case ( playlist, video ) of
( Just p, Just v ) ->
( Video p v Nothing
, Ports.registerVideo ( Twitch.videoId v, "videos/" ++ p.url ++ v.url, time )
)
_ -> ( Just p, Nothing ) ->
( Home Nothing, Cmd.none ) ( Playlist p Nothing, Cmd.none )
extraCmd = _ ->
case page of ( Home Nothing, Cmd.none )
Video _ _ _ ->
Cmd.none
_ -> extraCmd =
Ports.eraseVideo () case page of
in Video _ _ _ ->
( Loaded { m | page = page }, Cmd.batch [ cmd, extraCmd ] ) Cmd.none
( UrlRequested u, Loaded m ) -> _ ->
Ports.eraseVideo ()
in
( { m | page = page }, Cmd.batch [ cmd, extraCmd ] )
( UrlRequested u, m ) ->
case u of case u of
Browser.Internal url -> Browser.Internal url ->
( model, Nav.pushUrl m.key (Url.toString url) ) ( model, Nav.pushUrl m.key (Url.toString url) )
@ -248,9 +234,6 @@ update msg model =
Browser.External s -> Browser.External s ->
( model, Nav.load s ) ( model, Nav.load s )
_ ->
( model, Cmd.none )
splitter : String -> Maybe ( String, String ) splitter : String -> Maybe ( String, String )
splitter input = splitter input =

View File

@ -5,7 +5,7 @@ import Core
import Views import Views
main : Program { width : Int, height : Int } Core.FullModel Core.Msg main : Program { width : Int, height : Int } Core.Model Core.Msg
main = main =
Browser.application Browser.application
{ init = Core.init { init = Core.init

View File

@ -21,16 +21,16 @@ import Twitch
import Ui import Ui
view : Core.FullModel -> Browser.Document Core.Msg view : Core.Model -> Browser.Document Core.Msg
view model = view model =
let let
element = element =
case model of case model.playlists of
Core.Unloaded _ _ _ _ -> [] ->
Element.el [ Element.padding 10, Element.centerX ] spinner Element.el [ Element.padding 10, Element.centerX ] spinner
Core.Loaded m -> _ ->
viewContent m viewContent model
in in
{ title = title model { title = title model
, body = , body =
@ -47,22 +47,17 @@ view model =
} }
title : Core.FullModel -> String title : Core.Model -> String
title model = title model =
case model of case model.page of
Core.Unloaded _ _ _ _ -> Core.Home _ ->
Consts.url Consts.url
Core.Loaded m -> Core.Playlist p _ ->
case m.page of Consts.url ++ " - " ++ p.name
Core.Home _ ->
Consts.url
Core.Playlist p _ -> Core.Video p v _ ->
Consts.url ++ " - " ++ p.name Consts.url ++ " - " ++ p.name ++ " - " ++ v.name
Core.Video p v _ ->
Consts.url ++ " - " ++ p.name ++ " - " ++ v.name
viewContent : Core.Model -> Element Core.Msg viewContent : Core.Model -> Element Core.Msg