parent
7e2896dcf0
commit
b5fa55f49d
@ -8,7 +8,7 @@
|
||||
"debug": "node_modules/.bin/elm-live src/Main.elm --dir=public/ --output=public/app.js --debug",
|
||||
"deploy": "npm run build && node_modules/.bin/gh-pages --dist build/",
|
||||
"start": "node_modules/.bin/elm-live src/Main.elm --dir=public/ --output=public/app.js",
|
||||
"test": "node_modules/.bin/elm-make src/Main.elm --warn --output /tmp/tooty.html"
|
||||
"test": "node_modules/.bin/elm-make src/Main.elm --warn --output app.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -130,6 +130,12 @@ body {
|
||||
|
||||
.attachment-entry {
|
||||
margin-top: 5px;
|
||||
transition: 0.3s;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.attachment-entry:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.attachment-entry input {
|
||||
@ -274,3 +280,78 @@ body {
|
||||
text-align:center;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
/* Viewer */
|
||||
|
||||
.viewer {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
}
|
||||
|
||||
/* Modal Content (Image) */
|
||||
.viewer-content {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 80vw;
|
||||
max-height: 90vh;
|
||||
animation-name: zoom;
|
||||
animation-duration: 0.1s;
|
||||
}
|
||||
|
||||
@keyframes zoom {
|
||||
from { transform: scale(.9) }
|
||||
to { transform: scale(1) }
|
||||
}
|
||||
|
||||
.viewer > .close {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 35px;
|
||||
color: #eee;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
text-shadow: initial;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.viewer > .close:hover,
|
||||
.viewer > .close:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.prev, .next {
|
||||
font-size: 72px;
|
||||
opacity: .5;
|
||||
transition: opacity .5s;
|
||||
text-decoration: none;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.prev:hover,
|
||||
.next:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.prev:active, .prev:focus, .prev:hover,
|
||||
.next:active, .next:focus, .next:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 100% image width on smaller screens */
|
||||
@media only screen and (max-width: 700px) {
|
||||
.viewer-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,11 @@ type DraftMsg
|
||||
| ToggleSpoiler Bool
|
||||
|
||||
|
||||
type ViewerMsg
|
||||
= CloseViewer
|
||||
| OpenViewer (List Mastodon.Attachment) Mastodon.Attachment
|
||||
|
||||
|
||||
type
|
||||
Msg
|
||||
{-
|
||||
@ -56,6 +61,7 @@ type
|
||||
| Unreblog Int
|
||||
| Unreblogged (Result Mastodon.Error Mastodon.Status)
|
||||
| UserTimeline (Result Mastodon.Error (List Mastodon.Status))
|
||||
| ViewerEvent ViewerMsg
|
||||
|
||||
|
||||
type alias Draft =
|
||||
@ -67,6 +73,12 @@ type alias Draft =
|
||||
}
|
||||
|
||||
|
||||
type alias Viewer =
|
||||
{ attachments : List Mastodon.Attachment
|
||||
, attachment : Mastodon.Attachment
|
||||
}
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ server : String
|
||||
, registration : Maybe Mastodon.AppRegistration
|
||||
@ -80,6 +92,7 @@ type alias Model =
|
||||
, errors : List String
|
||||
, location : Navigation.Location
|
||||
, useGlobalTimeline : Bool
|
||||
, viewer : Maybe Viewer
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +134,7 @@ init flags location =
|
||||
, errors = []
|
||||
, location = location
|
||||
, useGlobalTimeline = False
|
||||
, viewer = Nothing
|
||||
}
|
||||
! [ initCommands flags.registration flags.client authCode ]
|
||||
|
||||
@ -308,6 +322,16 @@ updateDraft draftMsg draft =
|
||||
{ draft | in_reply_to = Nothing } ! []
|
||||
|
||||
|
||||
updateViewer : ViewerMsg -> Maybe Viewer -> ( Maybe Viewer, Cmd Msg )
|
||||
updateViewer viewerMsg viewer =
|
||||
case viewerMsg of
|
||||
CloseViewer ->
|
||||
Nothing ! []
|
||||
|
||||
OpenViewer attachments attachment ->
|
||||
(Just <| Viewer attachments attachment) ! []
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
@ -427,6 +451,13 @@ update msg model =
|
||||
in
|
||||
{ model | draft = draft } ! [ commands ]
|
||||
|
||||
ViewerEvent viewerMsg ->
|
||||
let
|
||||
( viewer, commands ) =
|
||||
updateViewer viewerMsg model.viewer
|
||||
in
|
||||
{ model | viewer = viewer } ! [ commands ]
|
||||
|
||||
SubmitDraft ->
|
||||
model
|
||||
! case model.client of
|
||||
|
65
src/View.elm
65
src/View.elm
@ -4,8 +4,9 @@ import Dict
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (..)
|
||||
import List.Extra exposing (elemIndex, getAt)
|
||||
import Mastodon
|
||||
import Model exposing (Model, Draft, DraftMsg(..), Msg(..))
|
||||
import Model exposing (Model, Draft, DraftMsg(..), Viewer, ViewerMsg(..), Msg(..))
|
||||
import ViewHelper
|
||||
|
||||
|
||||
@ -64,8 +65,8 @@ accountAvatarLink account =
|
||||
[ img [ class "avatar", src account.avatar ] [] ]
|
||||
|
||||
|
||||
attachmentPreview : Maybe Bool -> Mastodon.Attachment -> Html Msg
|
||||
attachmentPreview sensitive ({ url, preview_url } as attachment) =
|
||||
attachmentPreview : Maybe Bool -> List Mastodon.Attachment -> Mastodon.Attachment -> Html Msg
|
||||
attachmentPreview sensitive attachments ({ url, preview_url } as attachment) =
|
||||
let
|
||||
nsfw =
|
||||
case sensitive of
|
||||
@ -82,7 +83,8 @@ attachmentPreview sensitive ({ url, preview_url } as attachment) =
|
||||
a
|
||||
[ class "attachment-image"
|
||||
, href url
|
||||
, target "_blank"
|
||||
, ViewHelper.onClickWithPreventAndStop <|
|
||||
ViewerEvent (OpenViewer attachments attachment)
|
||||
, style
|
||||
[ ( "background"
|
||||
, "url(" ++ preview_url ++ ") center center / cover no-repeat"
|
||||
@ -113,7 +115,8 @@ attachmentListView { media_attachments, sensitive } =
|
||||
text ""
|
||||
|
||||
attachments ->
|
||||
ul [ class "attachments" ] <| List.map (attachmentPreview sensitive) attachments
|
||||
ul [ class "attachments" ] <|
|
||||
List.map (attachmentPreview sensitive attachments) attachments
|
||||
|
||||
|
||||
statusContentView : Mastodon.Status -> Html Msg
|
||||
@ -595,6 +598,52 @@ authView model =
|
||||
]
|
||||
|
||||
|
||||
viewerView : Viewer -> Html Msg
|
||||
viewerView { attachments, attachment } =
|
||||
let
|
||||
index =
|
||||
Maybe.withDefault -1 <| elemIndex attachment attachments
|
||||
|
||||
( prev, next ) =
|
||||
( getAt (index - 1) attachments, getAt (index + 1) attachments )
|
||||
|
||||
navLink label className target =
|
||||
case target of
|
||||
Nothing ->
|
||||
text ""
|
||||
|
||||
Just target ->
|
||||
a
|
||||
[ href ""
|
||||
, class className
|
||||
, ViewHelper.onClickWithPreventAndStop <|
|
||||
ViewerEvent (OpenViewer attachments target)
|
||||
]
|
||||
[ text label ]
|
||||
in
|
||||
div
|
||||
[ class "viewer"
|
||||
, tabindex -1
|
||||
, ViewHelper.onClickWithPreventAndStop <| ViewerEvent CloseViewer
|
||||
]
|
||||
[ span [ class "close" ] [ text "×" ]
|
||||
, navLink "❮" "prev" prev
|
||||
, case attachment.type_ of
|
||||
"image" ->
|
||||
img [ class "viewer-content", src attachment.url ] []
|
||||
|
||||
_ ->
|
||||
video
|
||||
[ class "viewer-content"
|
||||
, preload "auto"
|
||||
, autoplay True
|
||||
, loop True
|
||||
]
|
||||
[ source [ src attachment.url ] [] ]
|
||||
, navLink "❯" "next" next
|
||||
]
|
||||
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
div [ class "container-fluid" ]
|
||||
@ -605,4 +654,10 @@ view model =
|
||||
|
||||
Nothing ->
|
||||
authView model
|
||||
, case model.viewer of
|
||||
Just viewer ->
|
||||
viewerView viewer
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user