click on images to show them in a modal
This commit is contained in:
parent
6e2fa24261
commit
6978d27a8c
|
@ -11,7 +11,6 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
background: #000;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 3px solid var(--main-border);
|
border: 3px solid var(--main-border);
|
||||||
}
|
}
|
||||||
|
@ -28,8 +27,7 @@
|
||||||
background: var(--nav-bg)
|
background: var(--nav-bg)
|
||||||
}
|
}
|
||||||
.close-dialog-button {
|
.close-dialog-button {
|
||||||
margin: 0 0 2px;
|
padding: 0 0 7px;
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +39,13 @@
|
||||||
:global(dialog::backdrop, .backdrop) {
|
:global(dialog::backdrop, .backdrop) {
|
||||||
background: rgba(51, 51, 51, 0.9) !important; /* TODO: hack for Safari */
|
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>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
@ -53,6 +58,7 @@
|
||||||
if (typeof setImmediate === 'function' && navigator.userAgent.match(/Edge/)) {
|
if (typeof setImmediate === 'function' && navigator.userAgent.match(/Edge/)) {
|
||||||
this.getDialogElement().style.width = `${this.get('width')}px`
|
this.getDialogElement().style.width = `${this.get('width')}px`
|
||||||
}
|
}
|
||||||
|
this.getDialogElement().style.background = this.get('background') || '#000'
|
||||||
this.observe('shown', shown => {
|
this.observe('shown', shown => {
|
||||||
if (shown) {
|
if (shown) {
|
||||||
this.show()
|
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>
|
|
@ -5,7 +5,7 @@
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="play-video-button"
|
class="play-video-button"
|
||||||
aria-label="Play video: {{media.description || ''}}"
|
aria-label="Play video: {{media.description || ''}}"
|
||||||
on:click="onClickPlayVideoButton(media, media.description)">
|
on:click="onClickPlayVideoButton(media, getOriginalWidth(media), getOriginalHeight(media))">
|
||||||
<div class="svg-wrapper">
|
<div class="svg-wrapper">
|
||||||
<svg>
|
<svg>
|
||||||
<use xlink:href="#fa-play-circle" />
|
<use xlink:href="#fa-play-circle" />
|
||||||
|
@ -18,7 +18,12 @@
|
||||||
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
|
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
{{elseif media.type === 'gifv' && $autoplayGifs}}
|
{{else}}
|
||||||
|
<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
|
<video
|
||||||
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
|
class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
|
||||||
aria-label="Animated GIF: {{media.description || ''}}"
|
aria-label="Animated GIF: {{media.description || ''}}"
|
||||||
|
@ -50,6 +55,8 @@
|
||||||
width="{{getSmallWidth(media)}}"
|
width="{{getSmallWidth(media)}}"
|
||||||
height="{{getSmallHeight(media)}}"/>
|
height="{{getSmallHeight(media)}}"/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
@ -84,10 +91,10 @@
|
||||||
.play-video-button {
|
.play-video-button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.play-video-button .svg-wrapper {
|
.play-video-button .svg-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -108,6 +115,14 @@
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: var(--mask-opaque-bg);
|
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) {
|
@media (max-width: 767px) {
|
||||||
.status-media, .status-media video, .status-media img {
|
.status-media, .status-media video, .status-media img {
|
||||||
max-width: calc(100vw - 20px);
|
max-width: calc(100vw - 20px);
|
||||||
|
@ -120,20 +135,26 @@
|
||||||
|
|
||||||
import { imgLoad, imgLoadError } from '../../_utils/events'
|
import { imgLoad, imgLoadError } from '../../_utils/events'
|
||||||
import { showVideoDialog } from '../../_utils/showVideoDialog'
|
import { showVideoDialog } from '../../_utils/showVideoDialog'
|
||||||
|
import { showImageDialog } from '../../_utils/showImageDialog'
|
||||||
import NonAutoplayGifv from '../NonAutoplayGifv.html'
|
import NonAutoplayGifv from '../NonAutoplayGifv.html'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
helpers: {
|
helpers: {
|
||||||
getSmallWidth: media => media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH,
|
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,
|
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'),
|
hasNoNativeWidthHeight: media => !(media && media.meta && media.meta.small && typeof media.meta.small.width === 'number' && typeof media.meta.small.height === 'number'),
|
||||||
},
|
},
|
||||||
computed: {
|
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))
|
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: {
|
methods: {
|
||||||
async onClickPlayVideoButton(media, description) {
|
onClickPlayVideoButton(media, width, height) {
|
||||||
showVideoDialog(media.preview_url, media.url, description)
|
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: {
|
events: {
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
{{#if status.sensitive}}
|
{{#if status.sensitive}}
|
||||||
<div class="status-sensitive-media-container {{sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}}"
|
<div class="status-sensitive-media-container {{sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}}"
|
||||||
>
|
>
|
||||||
<button type="button" class="status-sensitive-media-button"
|
{{#if sensitiveShown}}
|
||||||
aria-label="{{sensitiveShown ? 'Hide sensitive media: ' : 'Show sensitive media'}}"
|
<button type="button"
|
||||||
|
class="status-sensitive-media-button"
|
||||||
|
aria-label="Hide sensitive media"
|
||||||
on:click="onClickSensitiveMediaButton()" >
|
on:click="onClickSensitiveMediaButton()" >
|
||||||
{{#if !sensitiveShown}}
|
|
||||||
<div class="status-sensitive-media-warning">
|
|
||||||
<span>
|
|
||||||
Sensitive content. Click to show.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
<div class="svg-wrapper">
|
<div class="svg-wrapper">
|
||||||
<svg>
|
<svg>
|
||||||
<use xlink:href="{{sensitiveShown ? '#fa-eye-slash' : '#fa-eye'}}" />
|
<use xlink:href="#fa-eye-slash" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{{#if sensitiveShown}}
|
|
||||||
<Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
|
<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}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -39,8 +48,6 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-sensitive-media-button:hover {
|
.status-sensitive-media-button:hover {
|
||||||
|
@ -54,12 +61,17 @@
|
||||||
.status-sensitive-media-shown .status-sensitive-media-button {
|
.status-sensitive-media-shown .status-sensitive-media-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
|
||||||
z-index: 90;
|
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 {
|
.status-sensitive-media-container.status-sensitive-media-hidden {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
|
@ -80,11 +92,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-sensitive-media-container .svg-wrapper {
|
.status-sensitive-media-container .svg-wrapper {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
@ -92,6 +99,13 @@
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: var(--mask-bg);
|
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 {
|
.status-sensitive-media-container.status-sensitive-media-shown .svg-wrapper {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +143,7 @@
|
||||||
$sensitivesShown[contextualStatusId] = !$sensitivesShown[contextualStatusId]
|
$sensitivesShown[contextualStatusId] = !$sensitivesShown[contextualStatusId]
|
||||||
this.store.set({'sensitivesShown': $sensitivesShown})
|
this.store.set({'sensitivesShown': $sensitivesShown})
|
||||||
this.fire('recalculateHeight')
|
this.fire('recalculateHeight')
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -1,13 +1,18 @@
|
||||||
<ModalDialog :shown>
|
<ModalDialog :shown background="#000">
|
||||||
<video poster="{{poster}}"
|
<video poster="{{poster}}"
|
||||||
src="{{src}}"
|
src="{{src}}"
|
||||||
|
width="{{width}}"
|
||||||
|
height="{{height}}"
|
||||||
aria-label="Video: {{description || ''}}"
|
aria-label="Video: {{description || ''}}"
|
||||||
controls
|
controls
|
||||||
/>
|
/>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
<style>
|
<style>
|
||||||
:global(.modal-dialog video) {
|
:global(.modal-dialog video) {
|
||||||
max-width: 100%;
|
object-fit: contain;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: calc(100vw - 20px);
|
||||||
|
max-height: calc(100vh - 100px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<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 VideoDialog from '../_components/status/VideoDialog.html'
|
||||||
import { createDialogElement } from './dialogs'
|
import { createDialogElement } from './dialogs'
|
||||||
|
|
||||||
export function showVideoDialog(poster, src, description) {
|
export function showVideoDialog(poster, src, width, height, description) {
|
||||||
let videoDialog = new VideoDialog({
|
let videoDialog = new VideoDialog({
|
||||||
target: createDialogElement('Video dialog'),
|
target: createDialogElement('Video dialog'),
|
||||||
data: {
|
data: {
|
||||||
poster: poster,
|
poster,
|
||||||
src: src,
|
src,
|
||||||
description: description
|
width,
|
||||||
|
height,
|
||||||
|
description
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
videoDialog.show()
|
videoDialog.show()
|
||||||
|
|
Loading…
Reference in a new issue