239 lines
6.1 KiB
Elm
239 lines
6.1 KiB
Elm
module GameList exposing (..)
|
|
|
|
import Dict exposing (Dict)
|
|
import Duration
|
|
import Element exposing (Element)
|
|
import Element.Background
|
|
import Element.Events
|
|
import Games.TicTacToe as TicTacToe exposing (TicTacToe)
|
|
import Layout
|
|
import Match exposing (Match)
|
|
import Material.Icons as Icons
|
|
import Pixels exposing (Pixels)
|
|
import Quantity exposing (Quantity)
|
|
import Theme
|
|
|
|
|
|
|
|
-- MODEL
|
|
|
|
|
|
type CreateGameType
|
|
= CreateTicTacToe
|
|
|
|
|
|
type Game
|
|
= GameTicTacToe String (Match TicTacToe)
|
|
|
|
|
|
type GameList
|
|
= GameList
|
|
{ ticTacToe : Dict String (Match TicTacToe)
|
|
}
|
|
|
|
|
|
type Msg
|
|
= AddTicTacToe { baseUrl : String, matchId : String }
|
|
| OnTicTacToe String (Match.Msg TicTacToe)
|
|
|
|
|
|
init : {} -> ( GameList, Cmd Msg )
|
|
init _ =
|
|
( GameList
|
|
{ ticTacToe = Dict.empty
|
|
}
|
|
, Cmd.none
|
|
)
|
|
|
|
|
|
|
|
-- UPDATE
|
|
|
|
|
|
update : Msg -> GameList -> ( GameList, Cmd Msg )
|
|
update msg ((GameList data) as model) =
|
|
case msg of
|
|
AddTicTacToe newGame ->
|
|
let
|
|
( newMdl, newM ) =
|
|
Match.init
|
|
{ autoScroll = Just (Duration.seconds 0.75)
|
|
, baseUrl = newGame.baseUrl
|
|
, decoder = TicTacToe.decoder
|
|
, empty = TicTacToe.empty
|
|
, matchId = newGame.matchId
|
|
}
|
|
in
|
|
( GameList { data | ticTacToe = Dict.insert newGame.matchId newMdl data.ticTacToe }
|
|
, Cmd.map (OnTicTacToe newGame.matchId) newM
|
|
)
|
|
|
|
OnTicTacToe key m ->
|
|
case Dict.get key data.ticTacToe of
|
|
Nothing ->
|
|
( model, Cmd.none )
|
|
|
|
Just mdl ->
|
|
case Match.update m mdl of
|
|
( newMdl, newM ) ->
|
|
( GameList { data | ticTacToe = Dict.insert key newMdl data.ticTacToe }
|
|
, Cmd.map (OnTicTacToe key) newM
|
|
)
|
|
|
|
|
|
|
|
-- SUBSCRIPTIONS
|
|
|
|
|
|
subscriptions : GameList -> Sub Msg
|
|
subscriptions (GameList data) =
|
|
Sub.batch
|
|
[ Dict.toList data.ticTacToe
|
|
|> List.map
|
|
(\( key, mdl ) ->
|
|
Sub.map (OnTicTacToe key) (Match.subscriptions mdl)
|
|
)
|
|
|> Sub.batch
|
|
]
|
|
|
|
|
|
|
|
-- VIEW
|
|
|
|
|
|
createGameToString : CreateGameType -> String
|
|
createGameToString cg =
|
|
case cg of
|
|
CreateTicTacToe ->
|
|
"tic-tac-toe"
|
|
|
|
|
|
viewCreateGame :
|
|
{ baseUrl : String
|
|
, flavor : Theme.Flavor
|
|
, height : Quantity Int Pixels
|
|
, onBaseUrl : String -> msg
|
|
, onPlayers : List String -> msg
|
|
, players : List String
|
|
, width : Quantity Int Pixels
|
|
}
|
|
-> Element msg
|
|
viewCreateGame data =
|
|
Element.none
|
|
|
|
|
|
viewGame :
|
|
{ flavor : Theme.Flavor
|
|
, game : Game
|
|
, height : Quantity Int Pixels
|
|
, onNavigateBack : msg
|
|
, toMsg : Msg -> msg
|
|
, width : Quantity Int Pixels
|
|
}
|
|
-> Element msg
|
|
viewGame data =
|
|
let
|
|
navBarHeight =
|
|
Pixels.pixels 200
|
|
|
|
showNavBar =
|
|
Quantity.ratio (Quantity.toFloatQuantity data.height) navBarHeight <= 3
|
|
|
|
gameHeight =
|
|
if showNavBar then
|
|
data.height |> Quantity.minus navBarHeight
|
|
|
|
else
|
|
data.height
|
|
in
|
|
Element.column
|
|
[ Element.height <| Element.px <| Pixels.inPixels data.height
|
|
, Element.width <| Element.px <| Pixels.inPixels data.width
|
|
]
|
|
[ if showNavBar then
|
|
Element.row
|
|
[ Element.Background.color (Theme.blueUI data.flavor)
|
|
, Element.height <| Element.px <| Pixels.inPixels navBarHeight
|
|
, Element.width <| Element.px <| Pixels.inPixels data.width
|
|
]
|
|
[ Layout.iconAsElement
|
|
{ color = Theme.blue data.flavor
|
|
, height = Pixels.inPixels navBarHeight
|
|
, icon = Icons.arrow_back
|
|
, width = Pixels.inPixels data.width
|
|
}
|
|
|> Element.el [ Element.Events.onClick data.onNavigateBack ]
|
|
]
|
|
|
|
else
|
|
Element.none
|
|
, viewMatch
|
|
{ flavor = data.flavor
|
|
, game = data.game
|
|
, height = gameHeight
|
|
, width = data.width
|
|
}
|
|
|> Element.map data.toMsg
|
|
]
|
|
|
|
|
|
viewMatch :
|
|
{ flavor : Theme.Flavor
|
|
, game : Game
|
|
, height : Quantity Int Pixels
|
|
, width : Quantity Int Pixels
|
|
}
|
|
-> Element Msg
|
|
viewMatch data =
|
|
case data.game of
|
|
GameTicTacToe key match ->
|
|
Match.view
|
|
{ flavor = data.flavor
|
|
, height = data.height
|
|
, match = match
|
|
, toMsg = OnTicTacToe key
|
|
, viewGame = TicTacToe.view
|
|
, width = data.width
|
|
}
|
|
|
|
|
|
viewSelection :
|
|
{ flavor : Theme.Flavor
|
|
, height : Quantity Int Pixels
|
|
, model : GameList
|
|
, onCreateGame : msg
|
|
, onNavigateToGame : Game -> msg
|
|
, width : Quantity Int Pixels
|
|
}
|
|
-> Element msg
|
|
viewSelection data =
|
|
case data.model of
|
|
GameList model ->
|
|
[ Layout.itemWithSubtext
|
|
{ color = Theme.mantle data.flavor
|
|
, leftIcon = always Element.none
|
|
, onPress = Just data.onCreateGame
|
|
, rightIcon = always Element.none
|
|
, text = "Create new game"
|
|
, title = "CREATE"
|
|
}
|
|
[]
|
|
|> List.singleton
|
|
, model.ticTacToe
|
|
|> Dict.toList
|
|
|> List.map
|
|
(\( key, match ) ->
|
|
Match.viewListItem
|
|
{ flavor = data.flavor
|
|
, height = Pixels.pixels 80
|
|
, match = match
|
|
, onPress = Just <| data.onNavigateToGame <| GameTicTacToe key match
|
|
, width = data.width
|
|
}
|
|
)
|
|
]
|
|
|> List.concat
|
|
|> Element.column
|
|
[ Element.centerX
|
|
]
|