module Main exposing (..) import Browser import Browser.Navigation as Nav import CommonElements exposing (..) import Element exposing (..) import NavRow exposing (..) import PageState exposing (..) import Session exposing (Session) import Url import Viewer exposing (..) type Model = Redirect Session | NotFound Session | About Session | Home Home.Model | Account Account.Model | Login Login.Model | Signup Signup.Model | Todo Todo.Model | Editor (Maybe UUID) Editor.Model type Msg = UrlChange Url.Url | Request Browser.UrlRequest | GotHomeMsg Home.Msg | GotAccountMsg Account.Msg | GotLoginMsg Login.Msg | GotSignupMsg Signup.Msg | GotEditorMsg Editor.Msg | GotTodoMsg Todo.Msg | GotSession Session init : Maybe Viewer -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init maybeViewer url key = changeRouteTo (Route.fromUrl url) (Redirect (Session.fromViewer navKey maybeViewer)) toSession : Model -> Session toSession page = case page of Redirect session -> session NotFound session -> session About session -> session Home home -> Home.toSession home Account settings -> Settings.toSession settings Login login -> Login.toSession login Signup signup -> Signup.toSession signup Todo todo -> Todo.toSession todo Editor _ editor -> Editor.toSession editor changeRouteTo : Maybe Route -> Model -> ( Model, Cmd Msg ) changeRouteTo maybeRoute model = let session = toSession model in case maybeRoute of Nothing -> ( NotFound session, Cmd.none ) Just Route.Root -> ( model, Route.replaceUrl (Session.navKey session) Route.Home ) Just Route.Logout -> ( model, Api.logout ) Just Route.NewTodo -> Editor.initNew session |> updateWith (Editor Nothing) GotEditorMsg model Just (Route.EditTodo slug) -> Editor.initEdit session slug |> updateWith (Editor (Just slug)) GotEditorMsg model Just Route.Account -> Account.init session |> updateWith Account GotAccountMsg model Just Route.Home -> Home.init session |> updateWith Home GotHomeMsg model Just Route.Login -> Login.init session |> updateWith Login GotLoginMsg model Just Route.Signup -> Signup.init session |> updateWith Signup GotSignupMsg model Just (Route.Profile username) -> Profile.init session username |> updateWith (Profile username) GotProfileMsg model Just (Route.Todo slug) -> Todo.init session slug |> updateWith Todo GotArticleMsg model update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case ( msg, model ) of ( _, _ ) -> ( model, Cmd.none ) updateWith : (subModel -> Model) -> (subMsg -> Msg) -> Model -> ( subModel, Cmd subMsg ) -> ( Model, Cmd Msg ) updateWith toModel toMsg model ( subModel, subCmd ) = ( toModel subModel , Cmd.map toMsg subCmd ) -- view takes current application state and is responsible -- for rendering the document based on it view : Model -> Browser.Document Msg view model = { title = "Elm App Test" , body = [ layout [ height fill ] (column [ width fill ] [ getNavRow model , getMainContent model ] ) ] } -- subscriptions takes the current state and -- maybe returns the subscriptions based on it (?) -- might be used to subscribe to different events based on -- the url, etc. subscriptions : Model -> Sub Msg subscriptions _ = Sub.none main : Program Value Model Msg main = Api.application Viewer.decoder { init = init , view = view , update = update , subscriptions = subscriptions , onUrlChange = UrlChange -- these are actual types from Msg , onUrlRequest = Request }