elm-matrix-sdk-beta/dev/Main.elm

304 lines
9.6 KiB
Elm
Raw Normal View History

2024-01-23 12:41:19 +00:00
module Main exposing (main)
{-| This module creates a browser document that allows users to look at various
documentation elements of the Elm Matrix SDK.
-}
import Browser
2024-01-23 17:45:19 +00:00
import Browser.Dom as Dom
2024-01-23 12:41:19 +00:00
import Browser.Navigation as Navigation
2024-01-23 17:45:19 +00:00
import Colors as C
import Dict exposing (Dict)
2024-01-23 12:41:19 +00:00
import DocsDisplay as Display
2024-01-23 17:45:19 +00:00
import Element exposing (Element)
import Element.Font as Font
import Element.Input as Input
import Internal.Tools.Hashdict
2024-01-23 12:41:19 +00:00
import Internal.Tools.Json as Json
2024-01-23 17:45:19 +00:00
import Internal.Tools.Mashdict
import Internal.Tools.Timestamp
import Internal.Values.Context
import Internal.Values.Envelope
import Internal.Values.Event
import Internal.Values.Settings
import Internal.Values.StateManager
import Json.Decode as D
import Route exposing (Route(..))
import Task
import Url
import Widget
import Widget.Material as Material
2024-01-23 12:41:19 +00:00
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = OnUrlChange
, onUrlRequest = OnUrlRequest
}
2024-01-23 17:45:19 +00:00
coders : Dict String ( Json.Docs, String -> Result String String )
coders =
Dict.fromList
[ ( "Context", shapeCoder <| Internal.Values.Context.coder )
, ( "Envelope", shapeCoder <| Internal.Values.Envelope.coder Json.value )
, ( "Event", shapeCoder <| Internal.Values.Event.coder )
, ( "Hashdict", shapeCoder <| Internal.Tools.Hashdict.coder .eventId Internal.Values.Event.coder )
, ( "Mashdict", shapeCoder <| Internal.Tools.Mashdict.coder .stateKey Internal.Values.Event.coder )
, ( "Settings", shapeCoder <| Internal.Values.Settings.coder )
, ( "StateManager", shapeCoder <| Internal.Values.StateManager.coder )
, ( "Timestamp", shapeCoder <| Internal.Tools.Timestamp.coder )
]
shapeCoder : Json.Coder a -> ( Json.Docs, String -> Result String String )
shapeCoder coder =
( Json.toDocs coder
, decoder coder
)
decoder : Json.Coder a -> String -> Result String String
decoder coder value =
D.decodeString (Json.decode coder) value
|> Result.mapError D.errorToString
|> Result.map Debug.toString
|> Result.map ((++) "Success! JSON decoded to Elm value: ")
2024-01-23 12:41:19 +00:00
type alias Model =
{ key : Navigation.Key
, page : Route.Route
2024-01-23 17:45:19 +00:00
, input : String
, valid : Maybe (Result String String)
2024-01-23 12:41:19 +00:00
}
type Msg
2024-01-23 17:45:19 +00:00
= OnDecodeString
| OnObjectClick String
| OnScreenMoved Bool
2024-01-23 12:41:19 +00:00
| OnUrlChange Url.Url
| OnUrlRequest Browser.UrlRequest
2024-01-23 17:45:19 +00:00
| OnWriteJSON String
2024-01-23 12:41:19 +00:00
-- INIT
init : () -> Url.Url -> Navigation.Key -> ( Model, Cmd Msg )
init () url key =
( { key = key
, page = Route.toRoute url
2024-01-23 17:45:19 +00:00
, input = ""
, valid = Nothing
2024-01-23 12:41:19 +00:00
}
, Cmd.none
)
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
2024-01-23 17:45:19 +00:00
OnDecodeString ->
case model.page of
ViewObject o ->
( { model
| valid =
coders
|> Dict.get o
|> Maybe.map Tuple.second
|> Maybe.map ((|>) model.input)
}
, Cmd.none
)
_ ->
( model, Cmd.none )
OnObjectClick name ->
( model
, Dom.getElement name
|> Task.andThen
(\data ->
Dom.setViewport
data.element.x
data.element.y
)
|> Task.map (always True)
|> Task.onError (\_ -> Task.succeed False)
|> Task.perform OnScreenMoved
)
OnScreenMoved _ ->
2024-01-23 12:41:19 +00:00
( model, Cmd.none )
OnUrlChange url ->
init () url model.key
OnUrlRequest (Browser.Internal url) ->
( model, Navigation.pushUrl model.key (Url.toString url) )
OnUrlRequest (Browser.External url) ->
( model, Navigation.load url )
2024-01-23 17:45:19 +00:00
OnWriteJSON text ->
( { model | input = text }, Cmd.none )
2024-01-23 12:41:19 +00:00
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Browser.Document Msg
view model =
{ title = Route.toString model.page ++ " | Elm Matrix SDK Docs"
, body =
2024-01-23 17:45:19 +00:00
[ Widget.menuBar (Material.menuBar <| C.defaultPalette C.stdPicker)
{ title =
Element.link []
{ url = "/"
, label =
"Elm Matrix SDK Docs"
|> Element.text
|> Element.el
[ C.font C.stdPicker.light.white
]
}
, deviceClass = Element.Phone
, openLeftSheet = Nothing
, openRightSheet = Nothing
, openTopSheet = Nothing
, primaryActions = []
, search = Nothing
}
, (case model.page of
ViewObject o ->
Element.column [ Element.spacing 10 ]
[ coders
|> Dict.get o
|> Maybe.map (Tuple.first >> showDocs)
|> Maybe.withDefault (Element.text "This object doesn't exist!")
, Element.column
[ Element.width Element.fill
, Element.height <| Element.minimum 100 <| Element.fill
]
[ Input.multiline
[ case model.valid of
Just (Err _) ->
C.background C.stdPicker.light.secondary
Just (Ok _) ->
C.background C.stdPicker.light.quaternary
Nothing ->
Element.width Element.fill
, Element.width Element.fill
]
{ onChange = OnWriteJSON
, text = model.input
, placeholder =
"Insert a test JSON object..."
|> Element.text
|> Input.placeholder []
|> Just
, label = Input.labelHidden "Test input JSON"
, spellcheck = False
}
, Widget.button
(Material.outlinedButton <| C.defaultPalette C.stdPicker)
{ text = "Check JSON"
, icon = always Element.none
, onPress = Just OnDecodeString
}
, case model.valid of
Nothing ->
Element.none
Just (Ok msg) ->
msg
|> Element.text
|> List.singleton
|> Element.paragraph
[ C.font <| C.stdPicker.dark.quaternary ]
Just (Err msg) ->
msg
|> Element.text
|> List.singleton
|> Element.paragraph
[ C.font <| C.stdPicker.dark.secondary ]
]
]
Home ->
Element.column [ Element.spacing 10 ]
(List.append
[ Element.paragraph []
[ Element.text "This is the Home of the Elm Matrix SDK JSON documentation tool."
]
, Element.paragraph []
[ Element.text "This tool helps you debug and explore JSON data types that are used by the Elm Matrix SDK."
]
]
(coders
|> Dict.keys
|> List.map
(\name ->
Element.link
[ C.font <| C.stdPicker.medium.primary
, Font.underline
]
{ url = "/object/" ++ name
, label = Element.text name
}
)
)
)
2024-01-23 12:41:19 +00:00
_ ->
Internal.Values.StateManager.coder
|> Json.toDocs
2024-01-23 17:45:19 +00:00
|> showDocs
)
|> Element.el
[ Element.paddingXY 120 120
, Element.height Element.fill
]
]
|> Element.column
[ Element.width Element.fill
, Element.height Element.fill
, Element.alignTop
]
|> Element.layout
[ C.background <| C.stdPicker.dark.white
, C.font <| C.stdPicker.dark.black
]
|> List.singleton
2024-01-23 12:41:19 +00:00
}
2024-01-23 17:45:19 +00:00
showDocs : Json.Docs -> Element Msg
showDocs =
Display.render >> Element.map OnObjectClick