Render image attachments in statuses. (#24)
* Render image attachments in statuses. * Add a doorhanger to NSFW images. Sorry Japan.
This commit is contained in:
parent
201c6f48ce
commit
3a487d6e02
@ -1,8 +1,16 @@
|
|||||||
|
body {
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
min-height: 75px;
|
min-height: 75px;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nsfw {
|
||||||
|
background: #493438;
|
||||||
|
}
|
||||||
|
|
||||||
.reblog > p:first-of-type {
|
.reblog > p:first-of-type {
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
@ -49,6 +57,53 @@
|
|||||||
color: #9baec8;
|
color: #9baec8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Attachments */
|
||||||
|
|
||||||
|
.attachments {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-entry {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-entry input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-entry label {
|
||||||
|
display: block;
|
||||||
|
background: #111;
|
||||||
|
opacity: .95;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 95%;
|
||||||
|
height: 10vh;
|
||||||
|
margin-bottom: -10vh;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-entry input:checked + label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 10vh;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: zoom-in;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Spoiler */
|
/* Spoiler */
|
||||||
|
|
||||||
.spoiled input[type=checkbox] {
|
.spoiled input[type=checkbox] {
|
||||||
|
93
src/View.elm
93
src/View.elm
@ -39,11 +39,66 @@ icon name =
|
|||||||
i [ class <| "glyphicon glyphicon-" ++ name ] []
|
i [ class <| "glyphicon glyphicon-" ++ name ] []
|
||||||
|
|
||||||
|
|
||||||
|
attachmentPreview : Maybe Bool -> Mastodon.Attachment -> Html Msg
|
||||||
|
attachmentPreview sensitive ({ url, preview_url } as attachment) =
|
||||||
|
let
|
||||||
|
nsfw =
|
||||||
|
case sensitive of
|
||||||
|
Just sensitive ->
|
||||||
|
sensitive
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
False
|
||||||
|
|
||||||
|
attId =
|
||||||
|
"att" ++ (toString attachment.id)
|
||||||
|
|
||||||
|
media =
|
||||||
|
a
|
||||||
|
[ class "attachment-image"
|
||||||
|
, href url
|
||||||
|
, target "_blank"
|
||||||
|
, style
|
||||||
|
[ ( "background"
|
||||||
|
, "url(" ++ preview_url ++ ") center center / cover no-repeat"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
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 : Mastodon.Status -> Html Msg
|
||||||
|
attachmentListView { media_attachments, sensitive } =
|
||||||
|
case media_attachments of
|
||||||
|
[] ->
|
||||||
|
text ""
|
||||||
|
|
||||||
|
attachments ->
|
||||||
|
ul [ class "attachments" ] <| List.map (attachmentPreview sensitive) attachments
|
||||||
|
|
||||||
|
|
||||||
statusContentView : Mastodon.Status -> Html Msg
|
statusContentView : Mastodon.Status -> Html Msg
|
||||||
statusContentView status =
|
statusContentView status =
|
||||||
case status.spoiler_text of
|
case status.spoiler_text of
|
||||||
"" ->
|
"" ->
|
||||||
div [ class "status-text" ] <| ViewHelper.formatContent status.content status.mentions
|
div [ class "status-text" ]
|
||||||
|
[ div [] <| ViewHelper.formatContent status.content status.mentions
|
||||||
|
, attachmentListView status
|
||||||
|
]
|
||||||
|
|
||||||
spoiler ->
|
spoiler ->
|
||||||
-- Note: Spoilers are dealt with using pure CSS.
|
-- Note: Spoilers are dealt with using pure CSS.
|
||||||
@ -55,12 +110,15 @@ statusContentView status =
|
|||||||
[ div [ class "spoiler" ] [ text status.spoiler_text ]
|
[ div [ class "spoiler" ] [ text status.spoiler_text ]
|
||||||
, input [ type_ "checkbox", id statusId, class "spoiler-toggler" ] []
|
, input [ type_ "checkbox", id statusId, class "spoiler-toggler" ] []
|
||||||
, label [ for statusId ] [ text "Reveal content" ]
|
, label [ for statusId ] [ text "Reveal content" ]
|
||||||
, div [ class "spoiled-content" ] <| (ViewHelper.formatContent status.content status.mentions)
|
, div [ class "spoiled-content" ]
|
||||||
|
[ div [] <| ViewHelper.formatContent status.content status.mentions
|
||||||
|
, attachmentListView status
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
statusView : Mastodon.Status -> Html Msg
|
statusView : Mastodon.Status -> Html Msg
|
||||||
statusView ({ account, content, reblog, mentions } as status) =
|
statusView ({ account, content, media_attachments, reblog, mentions } as status) =
|
||||||
let
|
let
|
||||||
accountLinkAttributes =
|
accountLinkAttributes =
|
||||||
[ href account.url
|
[ href account.url
|
||||||
@ -139,6 +197,21 @@ accountTimelineView account statuses label iconName =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
statusEntryView : Mastodon.Status -> Html Msg
|
||||||
|
statusEntryView status =
|
||||||
|
let
|
||||||
|
nsfwClass =
|
||||||
|
case status.sensitive of
|
||||||
|
Just True ->
|
||||||
|
"nsfw"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
""
|
||||||
|
in
|
||||||
|
li [ class <| "list-group-item " ++ nsfwClass ]
|
||||||
|
[ statusView status ]
|
||||||
|
|
||||||
|
|
||||||
timelineView : List Mastodon.Status -> String -> String -> Html Msg
|
timelineView : List Mastodon.Status -> String -> String -> Html Msg
|
||||||
timelineView statuses label iconName =
|
timelineView statuses label iconName =
|
||||||
div [ class "col-md-3" ]
|
div [ class "col-md-3" ]
|
||||||
@ -148,12 +221,7 @@ timelineView statuses label iconName =
|
|||||||
, text label
|
, text label
|
||||||
]
|
]
|
||||||
, ul [ class "list-group" ] <|
|
, ul [ class "list-group" ] <|
|
||||||
List.map
|
List.map statusEntryView statuses
|
||||||
(\s ->
|
|
||||||
li [ class "list-group-item status" ]
|
|
||||||
[ statusView s ]
|
|
||||||
)
|
|
||||||
statuses
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -162,12 +230,7 @@ draftView : Model -> Html Msg
|
|||||||
draftView { draft } =
|
draftView { draft } =
|
||||||
let
|
let
|
||||||
hasSpoiler =
|
hasSpoiler =
|
||||||
case draft.spoiler_text of
|
draft.spoiler_text /= Nothing
|
||||||
Nothing ->
|
|
||||||
False
|
|
||||||
|
|
||||||
Just _ ->
|
|
||||||
True
|
|
||||||
|
|
||||||
visibilityOptionView ( visibility, description ) =
|
visibilityOptionView ( visibility, description ) =
|
||||||
option [ value visibility ]
|
option [ value visibility ]
|
||||||
|
Loading…
Reference in New Issue
Block a user