module View.Status exposing ( statusView , statusActionsView , statusEntryView ) import Html exposing (..) import Html.Attributes exposing (..) import Html.Keyed as Keyed import Html.Lazy as Lazy import Mastodon.Helper exposing (extractStatusId) import Mastodon.Model exposing (..) import Types exposing (..) import View.Common as Common import View.Events exposing (..) import View.Formatter exposing (formatContent) type alias CurrentUser = Account attachmentPreview : String -> Maybe Bool -> List Attachment -> Attachment -> Html Msg attachmentPreview context sensitive attachments ({ url, preview_url } as attachment) = let nsfw = case sensitive of Just sensitive -> sensitive Nothing -> False attId = "att" ++ attachment.id ++ context media = a [ if nsfw then class "attachment-image nsfw" else class "attachment-image" , href url , onClickWithPreventAndStop <| ViewerEvent (OpenViewer attachments attachment) ] [ img [ src <| if preview_url == "" then url else preview_url ] [] ] in li [ class "attachment-entry" ] <| if nsfw then [ input [ type_ "radio", id attId ] [] , label [ for attId ] [ text "Sensitive content" , br [] [] , br [] [] , text "click to show image" ] , media ] else [ media ] attachmentListView : String -> Status -> Html Msg attachmentListView context { media_attachments, sensitive } = let keyedEntry attachments attachment = ( attachment.id , attachmentPreview context sensitive attachments attachment ) in case media_attachments of [] -> text "" attachments -> Keyed.ul [ class "attachments" ] <| List.map (keyedEntry attachments) attachments statusActionsView : Status -> CurrentUser -> Bool -> Html Msg statusActionsView status currentUser showApp = let sourceStatus = Mastodon.Helper.extractReblog status baseBtnClasses = "btn btn-sm btn-default" ( reblogClasses, reblogEvent ) = case status.reblogged of Just True -> ( baseBtnClasses ++ " reblogged", UnreblogStatus sourceStatus ) _ -> ( baseBtnClasses, ReblogStatus sourceStatus ) ( favClasses, favEvent ) = case status.favourited of Just True -> ( baseBtnClasses ++ " favourited", RemoveFavorite sourceStatus ) _ -> ( baseBtnClasses, AddFavorite sourceStatus ) in div [ class "btn-group actions" ] [ a [ class baseBtnClasses , onClickWithPreventAndStop <| DraftEvent (UpdateReplyTo status) ] [ Common.icon "share-alt" ] , if status.visibility == "private" then span [ class <| reblogClasses ++ " disabled" ] [ span [ title "Private" ] [ Common.icon "lock" ] ] else if status.visibility == "direct" then span [ class <| reblogClasses ++ " disabled" ] [ span [ title "Direct" ] [ Common.icon "envelope" ] ] else a [ class reblogClasses, onClickWithPreventAndStop reblogEvent ] [ Common.icon "fire", text (toString sourceStatus.reblogs_count) ] , a [ class favClasses, onClickWithPreventAndStop favEvent ] [ Common.icon "star", text (toString sourceStatus.favourites_count) ] , if Mastodon.Helper.sameAccount sourceStatus.account currentUser then a [ class <| baseBtnClasses ++ " btn-delete" , href "" , onClickWithPreventAndStop <| AskConfirm "Are you sure you want to delete this toot?" (DeleteStatus sourceStatus.id) NoOp ] [ Common.icon "trash" ] else text "" , a [ class baseBtnClasses, href (Maybe.withDefault "#" status.url), target "_blank" ] [ Common.icon "time", text <| Common.formatDate status.created_at ] , if showApp then Common.appLink (baseBtnClasses ++ " applink") status.application else text "" ] statusContentView : String -> Status -> Html Msg statusContentView context status = case status.spoiler_text of "" -> div [ class "status-text" ] [ div [ onClickWithStop <| OpenThread status ] <| formatContent status.content status.mentions , attachmentListView context status ] spoiler -> -- Note: Spoilers are dealt with using pure CSS. let statusId = "spoiler" ++ extractStatusId status.id ++ context in div [ class "status-text spoiled" ] [ div [ class "spoiler" , onClickWithStop <| OpenThread status ] [ text status.spoiler_text ] , input [ type_ "checkbox", id statusId, class "spoiler-toggler" ] [] , label [ for statusId ] [ text "Reveal content" ] , div [ class "spoiled-content" ] [ div [] <| formatContent status.content status.mentions , attachmentListView context status ] ] statusEntryView : String -> String -> CurrentUser -> Status -> Html Msg statusEntryView context className currentUser status = let nsfwClass = case status.sensitive of Just True -> "nsfw" _ -> "" liAttributes = [ class <| "list-group-item " ++ className ++ " " ++ nsfwClass ] ++ if context == "thread" then [ id <| "thread-status-" ++ extractStatusId status.id ] else [] in li liAttributes [ Lazy.lazy2 statusView context status , Lazy.lazy3 statusActionsView status currentUser (className == "thread-target") ] statusView : String -> Status -> Html Msg statusView context ({ account, content, media_attachments, reblog, mentions, pinned } as status) = let accountLinkAttributes = [ href <| "#account/" ++ account.id ] pin = if pinned then p [ class "status-info" ] [ Common.icon "pushpin" , text " Pinned status" ] else text "" in case reblog of Just (Reblog reblog) -> div [ class "reblog" ] [ p [ class "status-info" ] [ Common.icon "fire" , a (accountLinkAttributes ++ [ class "reblogger" ]) [ text <| " " ++ if account.display_name == "" then account.username else account.display_name] , text " boosted" ] , Lazy.lazy2 statusView context reblog ] Nothing -> div [ class "status" ] [ pin , Common.accountAvatarLink False account , div [ class "username" ] [ a accountLinkAttributes [ text (if account.display_name=="" then account.username else account.display_name) , span [ class "acct" ] [ text <| " @" ++ account.acct ] ] ] , Lazy.lazy2 statusContentView context status ]