click on images to show them in a modal

This commit is contained in:
Nolan Lawson 2018-02-04 15:59:42 -08:00
parent 6e2fa24261
commit 6978d27a8c
7 changed files with 187 additions and 78 deletions

View file

@ -11,7 +11,6 @@
position: fixed;
top: 50%;
transform: translate(0, -50%);
background: #000;
padding: 0;
border: 3px solid var(--main-border);
}
@ -28,8 +27,7 @@
background: var(--nav-bg)
}
.close-dialog-button {
margin: 0 0 2px;
padding: 0;
padding: 0 0 7px;
background: none;
border: none;
}
@ -41,6 +39,13 @@
:global(dialog::backdrop, .backdrop) {
background: rgba(51, 51, 51, 0.9) !important; /* TODO: hack for Safari */
}
@media (max-width: 767px) {
.close-dialog-button span {
padding: 0 10px 4px;
font-size: 32px;
}
}
</style>
<script>
@ -53,6 +58,7 @@
if (typeof setImmediate === 'function' && navigator.userAgent.match(/Edge/)) {
this.getDialogElement().style.width = `${this.get('width')}px`
}
this.getDialogElement().style.background = this.get('background') || '#000'
this.observe('shown', shown => {
if (shown) {
this.show()

View file

@ -0,0 +1,44 @@
<ModalDialog :shown background="var(--main-bg)">
{{#if type === 'gifv'}}
<video
aria-label="Animated GIF: {{description || ''}}"
poster="{{poster}}"
src="{{src}}"
width="{{width}}"
height="{{height}}"
autoplay
muted
loop
playsinline
/>
{{else}}
<img
src="{{src}}"
width="{{width}}"
height="{{height}}"
aria-label="{{description || ''}}"
/>
{{/if}}
</ModalDialog>
<style>
:global(.modal-dialog img, .modal-dialog video) {
object-fit: contain;
overflow: hidden;
max-width: calc(100vw - 20px);
max-height: calc(100vh - 100px);
}
</style>
<script>
import ModalDialog from '../ModalDialog.html'
export default {
components: {
ModalDialog
},
methods: {
async show() {
this.set({shown: true})
}
}
}
</script>

View file

@ -2,53 +2,60 @@
style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" >
{{#each mediaAttachments as media}}
{{#if media.type === 'video'}}
<button type="button"
class="play-video-button"
aria-label="Play video: {{media.description || ''}}"
on:click="onClickPlayVideoButton(media, media.description)">
<div class="svg-wrapper">
<svg>
<use xlink:href="#fa-play-circle" />
</svg>
</div>
<img alt="{{media.description || ''}}"
src="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
/>
</button>
{{elseif media.type === 'gifv' && $autoplayGifs}}
<video
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
aria-label="Animated GIF: {{media.description || ''}}"
poster="{{media.preview_url}}"
src="{{media.url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
autoplay
muted
loop
playsinline
/>
{{elseif media.type === 'gifv' && !$autoplayGifs}}
<NonAutoplayGifv
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
label="Animated GIF: {{media.description || ''}}"
poster="{{media.preview_url}}"
src="{{media.url}}"
staticSrc="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
<button type="button"
class="play-video-button"
aria-label="Play video: {{media.description || ''}}"
on:click="onClickPlayVideoButton(media, getOriginalWidth(media), getOriginalHeight(media))">
<div class="svg-wrapper">
<svg>
<use xlink:href="#fa-play-circle" />
</svg>
</div>
<img alt="{{media.description || ''}}"
src="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
/>
</button>
{{else}}
<img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
on:imgLoad="set({imageLoaded: true})"
on:imgLoadError="set({imageError: true})"
alt="{{media.description || ''}}"
src="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"/>
<button type="button"
class="show-image-button"
aria-label="Show image: {{media.description || ''}}"
on:click="onClickShowImageButton(media, getOriginalWidth(media), getOriginalHeight(media))">
{{#if media.type === 'gifv' && $autoplayGifs}}
<video
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
aria-label="Animated GIF: {{media.description || ''}}"
poster="{{media.preview_url}}"
src="{{media.url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
autoplay
muted
loop
playsinline
/>
{{elseif media.type === 'gifv' && !$autoplayGifs}}
<NonAutoplayGifv
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
label="Animated GIF: {{media.description || ''}}"
poster="{{media.preview_url}}"
src="{{media.url}}"
staticSrc="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"
/>
{{else}}
<img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
on:imgLoad="set({imageLoaded: true})"
on:imgLoadError="set({imageError: true})"
alt="{{media.description || ''}}"
src="{{media.preview_url}}"
width="{{getSmallWidth(media)}}"
height="{{getSmallHeight(media)}}"/>
{{/if}}
</button>
{{/if}}
{{/each}}
</div>
@ -84,10 +91,10 @@
.play-video-button {
margin: 0;
padding: 0;
position: relative;
border-radius: 0;
border: none;
background: none;
position: relative;
}
.play-video-button .svg-wrapper {
position: absolute;
@ -108,6 +115,14 @@
border-radius: 100%;
background: var(--mask-opaque-bg);
}
.show-image-button {
margin: 0;
padding: 0;
border-radius: 0;
border: none;
background: none;
cursor: zoom-in;
}
@media (max-width: 767px) {
.status-media, .status-media video, .status-media img {
max-width: calc(100vw - 20px);
@ -120,20 +135,26 @@
import { imgLoad, imgLoadError } from '../../_utils/events'
import { showVideoDialog } from '../../_utils/showVideoDialog'
import { showImageDialog } from '../../_utils/showImageDialog'
import NonAutoplayGifv from '../NonAutoplayGifv.html'
export default {
helpers: {
getSmallWidth: media => media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH,
getSmallHeight: media => media.meta && media.meta.small && typeof media.meta.small.height === 'number' ? media.meta.small.height : DEFAULT_MEDIA_HEIGHT,
getOriginalWidth: media => media.meta && media.meta.original && typeof media.meta.original.width === 'number' ? media.meta.original.width : DEFAULT_MEDIA_WIDTH,
getOriginalHeight: media => media.meta && media.meta.original && typeof media.meta.original.height === 'number' ? media.meta.original.height : DEFAULT_MEDIA_HEIGHT,
hasNoNativeWidthHeight: media => !(media && media.meta && media.meta.small && typeof media.meta.small.width === 'number' && typeof media.meta.small.height === 'number'),
},
computed: {
maxMediaWidth: (mediaAttachments) => Math.max.apply(Math, mediaAttachments.map(media => media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH))
},
methods: {
async onClickPlayVideoButton(media, description) {
showVideoDialog(media.preview_url, media.url, description)
onClickPlayVideoButton(media, width, height) {
showVideoDialog(media.preview_url, media.url, width, height, media.description)
},
onClickShowImageButton(media, width, height) {
showImageDialog(media.preview_url, media.url, media.type, width, height, media.description)
}
},
events: {

View file

@ -1,24 +1,33 @@
{{#if status.sensitive}}
<div class="status-sensitive-media-container {{sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}}"
>
<button type="button" class="status-sensitive-media-button"
aria-label="{{sensitiveShown ? 'Hide sensitive media: ' : 'Show sensitive media'}}"
{{#if sensitiveShown}}
<button type="button"
class="status-sensitive-media-button"
aria-label="Hide sensitive media"
on:click="onClickSensitiveMediaButton()" >
{{#if !sensitiveShown}}
<div class="status-sensitive-media-warning">
<span>
Sensitive content. Click to show.
</span>
</div>
{{/if}}
<div class="svg-wrapper">
<svg>
<use xlink:href="{{sensitiveShown ? '#fa-eye-slash' : '#fa-eye'}}" />
<use xlink:href="#fa-eye-slash" />
</svg>
</div>
</button>
{{#if sensitiveShown}}
<Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
{{else}}
<button type="button"
class="status-sensitive-media-button"
aria-label="Show sensitive media"
on:click="onClickSensitiveMediaButton()" >
<div class="status-sensitive-media-warning">
<span>Sensitive content. Click to show.</span>
</div>
<div class="svg-wrapper">
<svg>
<use xlink:href="#fa-eye" />
</svg>
</div>
</button>
{{/if}}
</div>
{{else}}
@ -39,8 +48,6 @@
padding: 0;
border: none;
background: none;
width: 100%;
height: 100%;
}
.status-sensitive-media-button:hover {
@ -54,12 +61,17 @@
.status-sensitive-media-shown .status-sensitive-media-button {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 90;
}
.status-sensitive-media-hidden .status-sensitive-media-button {
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.status-sensitive-media-container.status-sensitive-media-hidden {
width: 100%;
margin: 10px auto;
@ -80,11 +92,6 @@
}
.status-sensitive-media-container .svg-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: flex-start;
justify-content: flex-start;
@ -92,6 +99,13 @@
pointer-events: none;
background: var(--mask-bg);
}
.status-sensitive-media-hidden .svg-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.status-sensitive-media-container.status-sensitive-media-shown .svg-wrapper {
background: none;
}
@ -129,7 +143,7 @@
$sensitivesShown[contextualStatusId] = !$sensitivesShown[contextualStatusId]
this.store.set({'sensitivesShown': $sensitivesShown})
this.fire('recalculateHeight')
},
}
}
}
</script>

View file

@ -1,13 +1,18 @@
<ModalDialog :shown>
<ModalDialog :shown background="#000">
<video poster="{{poster}}"
src="{{src}}"
width="{{width}}"
height="{{height}}"
aria-label="Video: {{description || ''}}"
controls
/>
</ModalDialog>
<style>
:global(.modal-dialog video) {
max-width: 100%;
object-fit: contain;
overflow: hidden;
max-width: calc(100vw - 20px);
max-height: calc(100vh - 100px);
}
</style>
<script>

View file

@ -0,0 +1,17 @@
import ImageDialog from '../_components/status/ImageDialog.html'
import { createDialogElement } from './dialogs'
export function showImageDialog(poster, src, type, width, height, description) {
let imageDialog = new ImageDialog({
target: createDialogElement('Image dialog'),
data: {
poster,
src,
type,
width,
height,
description
}
})
imageDialog.show()
}

View file

@ -1,13 +1,15 @@
import VideoDialog from '../_components/status/VideoDialog.html'
import { createDialogElement } from './dialogs'
export function showVideoDialog(poster, src, description) {
export function showVideoDialog(poster, src, width, height, description) {
let videoDialog = new VideoDialog({
target: createDialogElement('Video dialog'),
data: {
poster: poster,
src: src,
description: description
poster,
src,
width,
height,
description
}
})
videoDialog.show()