module Main exposing (main) import Browser import Browser.Navigation as Nav import Shared exposing (Flags) import Spa.Document as Document exposing (Document) import Spa.Generated.Pages as Pages import Spa.Generated.Route as Route exposing (Route) import Url exposing (Url) main : Program Flags Model Msg main = Browser.application { init = init , update = update , subscriptions = subscriptions , view = view >> Document.toBrowserDocument , onUrlRequest = LinkClicked , onUrlChange = UrlChanged } -- INIT type alias Model = { shared : Shared.Model , page : Pages.Model } init : Flags -> Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = let ( shared, sharedCmd ) = Shared.init flags url key ( page, pageCmd ) = Pages.init (fromUrl url) shared savedShare = Pages.save page shared in ( Model savedShare page , Cmd.batch [ Cmd.map Shared sharedCmd , Cmd.map Pages pageCmd ] ) -- UPDATE type Msg = LinkClicked Browser.UrlRequest | UrlChanged Url | Shared Shared.Msg | Pages Pages.Msg update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of LinkClicked (Browser.Internal url) -> ( model , Nav.pushUrl model.shared.key (Url.toString url) ) LinkClicked (Browser.External href) -> ( model , Nav.load href ) UrlChanged url -> let original = model.shared shared = { original | url = url } ( page, pageCmd ) = Pages.init (fromUrl url) shared in ( { model | page = page, shared = Pages.save page shared } , Cmd.map Pages pageCmd ) Shared sharedMsg -> let ( shared, sharedCmd ) = Shared.update sharedMsg model.shared ( page, pageCmd ) = Pages.load model.page shared in ( { model | page = page, shared = shared } , Cmd.batch [ Cmd.map Shared sharedCmd , Cmd.map Pages pageCmd ] ) Pages pageMsg -> let ( page, pageCmd ) = Pages.update pageMsg model.page shared = Pages.save page model.shared in ( { model | page = page, shared = shared } , Cmd.map Pages pageCmd ) view : Model -> Document Msg view model = Shared.view { page = Pages.view model.page |> Document.map Pages , toMsg = Shared } model.shared subscriptions : Model -> Sub Msg subscriptions model = Sub.batch [ Shared.subscriptions model.shared |> Sub.map Shared , Pages.subscriptions model.page |> Sub.map Pages ] -- URL fromUrl : Url -> Route fromUrl = Route.fromUrl >> Maybe.withDefault Route.NotFound