tooty/src/View.elm
Vincent Jousse 201c6f48ce WIP: Display user account (#13)
* Display user account information in console

* Review's modifications

* Load user on mention click

* Display account information

* Reviews

* Undo messy refactoring

* Remove unused function
2017-04-22 10:16:14 +02:00

327 lines
12 KiB
Elm

module View exposing (view)
import Dict
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Mastodon
import Model exposing (Model, DraftMsg(..), Msg(..))
import ViewHelper
visibilities : Dict.Dict String String
visibilities =
Dict.fromList
[ ( "public", "post to public timelines" )
, ( "unlisted", "do not show in public timelines" )
, ( "private", "post to followers only" )
, ( "direct", "post to mentioned users only" )
]
errorView : String -> Html Msg
errorView error =
div [ class "alert alert-danger" ] [ text error ]
errorsListView : Model -> Html Msg
errorsListView model =
case model.errors of
[] ->
text ""
errors ->
div [] <| List.map errorView model.errors
icon : String -> Html Msg
icon name =
i [ class <| "glyphicon glyphicon-" ++ name ] []
statusContentView : Mastodon.Status -> Html Msg
statusContentView status =
case status.spoiler_text of
"" ->
div [ class "status-text" ] <| ViewHelper.formatContent status.content status.mentions
spoiler ->
-- Note: Spoilers are dealt with using pure CSS.
let
statusId =
"spoiler" ++ (toString status.id)
in
div [ class "status-text spoiled" ]
[ div [ class "spoiler" ] [ text status.spoiler_text ]
, input [ type_ "checkbox", id statusId, class "spoiler-toggler" ] []
, label [ for statusId ] [ text "Reveal content" ]
, div [ class "spoiled-content" ] <| (ViewHelper.formatContent status.content status.mentions)
]
statusView : Mastodon.Status -> Html Msg
statusView ({ account, content, reblog, mentions } as status) =
let
accountLinkAttributes =
[ href account.url
-- When clicking on a status, we should not let the browser
-- redirect to a new page. That's why we're preventing the default
-- behavior here
, ViewHelper.onClickWithPreventAndStop (OnLoadUserAccount account.id)
]
in
case reblog of
Just (Mastodon.Reblog reblog) ->
div [ class "reblog" ]
[ p []
[ icon "fire"
, a (accountLinkAttributes ++ [ class "reblogger" ])
[ text <| " " ++ account.username ]
, text " boosted"
]
, statusView reblog
]
Nothing ->
div [ class "status" ]
[ img [ class "avatar", src account.avatar ] []
, div [ class "username" ]
[ a accountLinkAttributes
[ text account.display_name
, span [ class "acct" ] [ text <| " @" ++ account.username ]
]
]
, statusContentView status
]
accountTimelineView : Mastodon.Account -> List Mastodon.Status -> String -> String -> Html Msg
accountTimelineView account statuses label iconName =
div [ class "col-md-3" ]
[ div [ class "panel panel-default" ]
[ div [ class "panel-heading" ]
[ icon iconName
, text label
]
, div [ class "account-detail", style [ ( "background-image", "url('" ++ account.header ++ "')" ) ] ]
[ div [ class "opacity-layer" ]
[ img [ src account.avatar ] []
, span [ class "account-display-name" ] [ text account.display_name ]
, span [ class "account-username" ] [ text ("@" ++ account.username) ]
, span [ class "account-note" ] (ViewHelper.formatContent account.note [])
]
]
, div [ class "row account-infos" ]
[ div [ class "col-md-4" ]
[ text "Statuses"
, br [] []
, text <| toString account.statuses_count
]
, div [ class "col-md-4" ]
[ text "Following"
, br [] []
, text <| toString account.following_count
]
, div [ class "col-md-4" ]
[ text "Followers"
, br [] []
, text <| toString account.followers_count
]
]
, ul [ class "list-group" ] <|
List.map
(\s ->
li [ class "list-group-item status" ]
[ statusView s ]
)
statuses
]
]
timelineView : List Mastodon.Status -> String -> String -> Html Msg
timelineView statuses label iconName =
div [ class "col-md-3" ]
[ div [ class "panel panel-default" ]
[ div [ class "panel-heading" ]
[ icon iconName
, text label
]
, ul [ class "list-group" ] <|
List.map
(\s ->
li [ class "list-group-item status" ]
[ statusView s ]
)
statuses
]
]
draftView : Model -> Html Msg
draftView { draft } =
let
hasSpoiler =
case draft.spoiler_text of
Nothing ->
False
Just _ ->
True
visibilityOptionView ( visibility, description ) =
option [ value visibility ]
[ text <| visibility ++ ": " ++ description ]
in
div [ class "col-md-3" ]
[ div [ class "panel panel-default" ]
[ div [ class "panel-heading" ] [ icon "envelope", text "Post a message" ]
, div [ class "panel-body" ]
[ Html.form [ class "form", onSubmit SubmitDraft ]
[ div [ class "form-group checkbox" ]
[ label []
[ input
[ type_ "checkbox"
, onCheck <| DraftEvent << ToggleSpoiler
, checked hasSpoiler
]
[]
, text " Add a spoiler"
]
]
, if hasSpoiler then
div [ class "form-group" ]
[ label [ for "spoiler" ] [ text "Visible part" ]
, textarea
[ id "spoiler"
, class "form-control"
, rows 5
, placeholder "This text will always be visible."
, onInput <| DraftEvent << UpdateSpoiler
, required True
, value <| Maybe.withDefault "" draft.spoiler_text
]
[]
]
else
text ""
, div [ class "form-group" ]
[ label [ for "status" ]
[ text <|
if hasSpoiler then
"Hidden part"
else
"Status"
]
, textarea
[ id "status"
, class "form-control"
, rows 8
, placeholder <|
if hasSpoiler then
"This text will be hidden by default, as you have enabled a spoiler."
else
"Once upon a time..."
, onInput <| DraftEvent << UpdateStatus
, required True
, value draft.status
]
[]
]
, div [ class "form-group" ]
[ label [ for "visibility" ] [ text "Visibility" ]
, select
[ id "visibility"
, class "form-control"
, onInput <| DraftEvent << UpdateVisibility
, required True
, value draft.visibility
]
<|
List.map visibilityOptionView <|
Dict.toList visibilities
]
, div [ class "form-group checkbox" ]
[ label []
[ input
[ type_ "checkbox"
, onCheck <| DraftEvent << UpdateSensitive
, checked draft.sensitive
]
[]
, text " This post is NSFW"
]
]
, p [ class "text-right" ]
[ button [ class "btn btn-primary" ]
[ text "Toot!" ]
]
]
]
]
]
homepageView : Model -> Html Msg
homepageView model =
div [ class "row" ]
[ draftView model
, timelineView model.userTimeline "Home timeline" "home"
, timelineView model.localTimeline "Local timeline" "th-large"
, case model.account of
Just account ->
-- Todo: Load the user timeline
accountTimelineView account [] "Account" "user"
Nothing ->
timelineView model.publicTimeline "Public timeline" "globe"
]
authView : Model -> Html Msg
authView model =
div [ class "col-md-4 col-md-offset-4" ]
[ div [ class "panel panel-default" ]
[ div [ class "panel-heading" ] [ text "Authenticate" ]
, div [ class "panel-body" ]
[ Html.form [ class "form", onSubmit Register ]
[ div [ class "form-group" ]
[ label [ for "server" ] [ text "Mastodon server root URL" ]
, input
[ type_ "url"
, class "form-control"
, id "server"
, required True
, placeholder "https://mastodon.social"
, value model.server
, pattern "https://.+"
, onInput ServerChange
]
[]
, p [ class "help-block" ]
[ text <|
"You'll be redirected to that server to authenticate yourself. "
++ "We don't have access to your password."
]
]
, button [ class "btn btn-primary", type_ "submit" ]
[ text "Sign into Tooty" ]
]
]
]
]
view : Model -> Html Msg
view model =
div [ class "container-fluid" ]
[ h1 [] [ text "tooty" ]
, errorsListView model
, case model.client of
Just client ->
homepageView model
Nothing ->
authView model
]