click on images to show them in a modal
This commit is contained in:
parent
6e2fa24261
commit
6978d27a8c
|
@ -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()
|
||||
|
|
44
routes/_components/status/ImageDialog.html
Normal file
44
routes/_components/status/ImageDialog.html
Normal 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>
|
|
@ -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: {
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
17
routes/_utils/showImageDialog.js
Normal file
17
routes/_utils/showImageDialog.js
Normal 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()
|
||||
}
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue