240 lines
5.7 KiB
Elm
240 lines
5.7 KiB
Elm
module Main exposing (main)
|
|
|
|
import Browser exposing (Document)
|
|
import Browser.Navigation as Nav
|
|
import Html exposing (Html, a, footer, h1, li, nav, text, ul)
|
|
import Html.Attributes exposing (classList, href)
|
|
import Html.Lazy exposing (lazy)
|
|
import PhotoFolders as Folders
|
|
import PhotoGroove as Gallery
|
|
import Url exposing (Url)
|
|
import Url.Parser as Parser exposing ((</>), Parser, s)
|
|
|
|
|
|
type alias Model =
|
|
{ page : Page
|
|
, version : Float
|
|
, key : Nav.Key
|
|
}
|
|
|
|
|
|
type Page
|
|
= GalleryPage Gallery.Model
|
|
| FoldersPage Folders.Model
|
|
| NotFound
|
|
|
|
|
|
type Route
|
|
= Gallery
|
|
| Folders
|
|
| SelectedPhoto String
|
|
|
|
|
|
view : Model -> Document Msg
|
|
view model =
|
|
let
|
|
title =
|
|
case model.page of
|
|
FoldersPage _ ->
|
|
Folders.pageTitle
|
|
|
|
GalleryPage _ ->
|
|
Gallery.pageTitle
|
|
|
|
_ ->
|
|
"Not Found"
|
|
|
|
content =
|
|
case model.page of
|
|
FoldersPage folders ->
|
|
Folders.view folders
|
|
|> Html.map GotFoldersMsg
|
|
|
|
GalleryPage gallery ->
|
|
Gallery.view gallery
|
|
|> Html.map GotGalleryMsg
|
|
|
|
NotFound ->
|
|
text "Not Found"
|
|
in
|
|
{ title = "Photo Groove | " ++ title
|
|
, body =
|
|
[ lazy viewHeader model.page
|
|
, content
|
|
, viewFooter
|
|
]
|
|
}
|
|
|
|
|
|
viewHeader : Page -> Html Msg
|
|
viewHeader page =
|
|
let
|
|
logo =
|
|
h1 [] [ text "Photo Groove" ]
|
|
|
|
links =
|
|
ul []
|
|
[ navLink Folders { url = "/", caption = "Folders" }
|
|
, navLink Gallery { url = "/gallery", caption = "Gallery" }
|
|
]
|
|
|
|
navLink : Route -> { url : String, caption : String } -> Html Msg
|
|
navLink targetRoute { url, caption } =
|
|
li [ classList [ ( "active", isActive { link = targetRoute, page = page } ) ] ]
|
|
[ a [ href url ] [ text caption ] ]
|
|
in
|
|
nav [] [ logo, links ]
|
|
|
|
|
|
isActive : { link : Route, page : Page } -> Bool
|
|
isActive { link, page } =
|
|
case ( link, page ) of
|
|
( Gallery, GalleryPage _ ) ->
|
|
True
|
|
|
|
( Gallery, _ ) ->
|
|
False
|
|
|
|
( Folders, FoldersPage _ ) ->
|
|
True
|
|
|
|
( Folders, _ ) ->
|
|
False
|
|
|
|
( SelectedPhoto _, _ ) ->
|
|
False
|
|
|
|
|
|
viewFooter : Html Msg
|
|
viewFooter =
|
|
footer []
|
|
[ text "One is never alone with a rubber duck. -Douglas Adams"
|
|
]
|
|
|
|
|
|
type Msg
|
|
= ClickedLink Browser.UrlRequest
|
|
| ChangedUrl Url
|
|
| GotGalleryMsg Gallery.Msg
|
|
| GotFoldersMsg Folders.Msg
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
|
update msg model =
|
|
case msg of
|
|
ClickedLink (Browser.External href) ->
|
|
( model, Nav.load href )
|
|
|
|
ClickedLink (Browser.Internal url) ->
|
|
( model, Nav.pushUrl model.key (Url.toString url) )
|
|
|
|
ChangedUrl url ->
|
|
updateUrl url model
|
|
|
|
GotGalleryMsg galleryMsg ->
|
|
case model.page of
|
|
GalleryPage gallery ->
|
|
toGallery model (Gallery.update galleryMsg gallery)
|
|
|
|
_ ->
|
|
( model, Cmd.none )
|
|
|
|
GotFoldersMsg foldersMsg ->
|
|
case model.page of
|
|
FoldersPage folders ->
|
|
toFolders model (Folders.update foldersMsg folders)
|
|
|
|
_ ->
|
|
( model, Cmd.none )
|
|
|
|
|
|
toGallery : Model -> ( Gallery.Model, Cmd Gallery.Msg ) -> ( Model, Cmd Msg )
|
|
toGallery model ( galleryModel, galleryCmd ) =
|
|
( { model | page = GalleryPage galleryModel }
|
|
, Cmd.map GotGalleryMsg galleryCmd
|
|
)
|
|
|
|
|
|
toFolders : Model -> ( Folders.Model, Cmd Folders.Msg ) -> ( Model, Cmd Msg )
|
|
toFolders model ( foldersModel, foldersCmd ) =
|
|
( { model | page = FoldersPage foldersModel }
|
|
, Cmd.map GotFoldersMsg foldersCmd
|
|
)
|
|
|
|
|
|
subscriptions : Model -> Sub Msg
|
|
subscriptions model =
|
|
case model.page of
|
|
GalleryPage gallery ->
|
|
Gallery.subscriptions gallery
|
|
|> Sub.map GotGalleryMsg
|
|
|
|
_ ->
|
|
Sub.none
|
|
|
|
|
|
init : Float -> Url -> Nav.Key -> ( Model, Cmd Msg )
|
|
init version url key =
|
|
updateUrl
|
|
url
|
|
{ page = NotFound
|
|
, version = version
|
|
, key = key
|
|
}
|
|
|
|
|
|
mergeFolders : Model -> ( Folders.Model, Cmd Folders.Msg ) -> ( Model, Cmd Msg )
|
|
mergeFolders model foldersTuple =
|
|
case model.page of
|
|
FoldersPage oldModel ->
|
|
( { model
|
|
| page =
|
|
FoldersPage <|
|
|
Folders.merge
|
|
{ oldModel = oldModel
|
|
, newModel = Tuple.first foldersTuple
|
|
}
|
|
}
|
|
, Cmd.none
|
|
)
|
|
|
|
_ ->
|
|
toFolders model foldersTuple
|
|
|
|
|
|
updateUrl : Url -> Model -> ( Model, Cmd Msg )
|
|
updateUrl url model =
|
|
case Parser.parse parser url of
|
|
Just Gallery ->
|
|
toGallery model <| Gallery.init model.version
|
|
|
|
Just Folders ->
|
|
mergeFolders model <| Folders.init Nothing
|
|
|
|
Just (SelectedPhoto filename) ->
|
|
mergeFolders model <| Folders.init <| Just filename
|
|
|
|
Nothing ->
|
|
( { model | page = NotFound }, Cmd.none )
|
|
|
|
|
|
parser : Parser (Route -> a) a
|
|
parser =
|
|
Parser.oneOf
|
|
[ Parser.map Folders Parser.top
|
|
, Parser.map Gallery (s "gallery")
|
|
, Parser.map SelectedPhoto (s "photos" </> Parser.string)
|
|
]
|
|
|
|
|
|
main : Program Float Model Msg
|
|
main =
|
|
Browser.application
|
|
{ init = init
|
|
, subscriptions = subscriptions
|
|
, update = update
|
|
, view = view
|
|
, onUrlRequest = ClickedLink
|
|
, onUrlChange = ChangedUrl
|
|
}
|