dotfiles/templates/website/frontend/src/Shared.elm
2025-10-01 19:51:55 -05:00

159 lines
3.4 KiB
Elm
Executable file

module Shared exposing
( Flags, decoder
, Model, Msg
, init, update, subscriptions
)
{-|
@docs Flags, decoder
@docs Model, Msg
@docs init, update, subscriptions
-}
import Browser.Events as BR exposing (..)
import Config.Style.Colour.Types
exposing
( Theme(..)
, themeFromString
, themeToString
)
import Config.Style.Fonts exposing (FontScale, createFontScale)
import Dict
import Effect exposing (Effect, none)
import Element as E exposing (..)
import Json.Decode exposing (..)
import Ports
import Process
import Route exposing (Route)
import Route.Path
import Shared.Model exposing (..)
import Shared.Msg
import Task
-- FLAGS
type alias Flags =
{ height : Int
, width : Int
, baseFontSize : Float
}
decoder : Json.Decode.Decoder Flags
decoder =
Json.Decode.map3
(\height width baseFontSize ->
{ height = height
, width = width
, baseFontSize = baseFontSize
}
)
(field "height" int)
(field "width" int)
(field "baseFontSize" float)
-- INIT
type alias Model =
Shared.Model.Model
init : Result Json.Decode.Error Flags -> Route () -> ( Model, Effect Msg )
init flagsResult route =
( modelFromFlagsResult flagsResult
, Effect.sendCmd (Ports.checkAssetsLoaded ())
)
modelFromFlagsResult : Result Error Flags -> Model
modelFromFlagsResult f =
case f of
Ok flags ->
{ device = classifyDevice flags
, height = flags.height
, width = flags.width
, theme = Dark
, fontScale = createFontScale flags.baseFontSize
, isLoading = True
, isFadingOut = False
}
Err e ->
{ device =
classifyDevice
{ height = 0
, width = 0
}
, height = 10
, width = 10
, theme = Dark
, fontScale = createFontScale 16.0
, isLoading = True
, isFadingOut = False
}
-- UPDATE
type alias Msg =
Shared.Msg.Msg
update : Route () -> Msg -> Model -> ( Model, Effect Msg )
update route msg model =
case msg of
Shared.Msg.LoadTheme themeString ->
( { model | theme = themeFromString themeString }
, Effect.none
)
Shared.Msg.ToggleTheme ->
( model
, Effect.sendCmd (Ports.saveTheme "toggle")
)
Shared.Msg.Resize width height ->
( { model
| device =
{ height = height
, width = width
}
|> E.classifyDevice
, height = height
, width = width
}
, Effect.none
)
Shared.Msg.LoadingComplete ->
( { model | isFadingOut = True }
, Effect.sendCmd (Process.sleep 600 |> Task.perform (\_ -> Shared.Msg.StartFadeOut))
)
Shared.Msg.StartFadeOut ->
( { model | isLoading = False, isFadingOut = False }
, Effect.none
)
-- SUBSCRIPTIONS
subscriptions : Route () -> Model -> Sub Msg
subscriptions route model =
Sub.batch
[ BR.onResize Shared.Msg.Resize
, Ports.loadTheme Shared.Msg.LoadTheme
, Ports.assetsLoaded (\_ -> Shared.Msg.LoadingComplete)
]