feat: add carousel for media modal (#928)
This commit is contained in:
parent
2ef4743b3c
commit
9d594f0bac
|
@ -24,7 +24,7 @@ const builders = [
|
||||||
rebuild: buildInlineScript
|
rebuild: buildInlineScript
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
watch: 'src/bin/svgs.js',
|
watch: 'bin/svgs.js',
|
||||||
comment: '<!-- inline SVG -->',
|
comment: '<!-- inline SVG -->',
|
||||||
rebuild: buildSvg
|
rebuild: buildSvg
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,10 @@ module.exports = [
|
||||||
{ id: 'fa-times', src: 'src/thirdparty/font-awesome-svg-png/white/svg/times.svg' },
|
{ id: 'fa-times', src: 'src/thirdparty/font-awesome-svg-png/white/svg/times.svg' },
|
||||||
{ id: 'fa-volume-off', src: 'src/thirdparty/font-awesome-svg-png/white/svg/volume-off.svg' },
|
{ id: 'fa-volume-off', src: 'src/thirdparty/font-awesome-svg-png/white/svg/volume-off.svg' },
|
||||||
{ id: 'fa-volume-up', src: 'src/thirdparty/font-awesome-svg-png/white/svg/volume-up.svg' },
|
{ id: 'fa-volume-up', src: 'src/thirdparty/font-awesome-svg-png/white/svg/volume-up.svg' },
|
||||||
{ id: 'fa-link', src: 'src/thirdparty/font-awesome-svg-png/white/svg/link.svg' }
|
{ id: 'fa-link', src: 'src/thirdparty/font-awesome-svg-png/white/svg/link.svg' },
|
||||||
|
{ id: 'fa-circle', src: 'src/thirdparty/font-awesome-svg-png/white/svg/circle.svg' },
|
||||||
|
{ id: 'fa-circle-o', src: 'src/thirdparty/font-awesome-svg-png/white/svg/circle-o.svg' },
|
||||||
|
{ id: 'fa-angle-left', src: 'src/thirdparty/font-awesome-svg-png/white/svg/angle-left.svg' },
|
||||||
|
{ id: 'fa-angle-right', src: 'src/thirdparty/font-awesome-svg-png/white/svg/angle-right.svg' }
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -99,6 +99,22 @@
|
||||||
fill: var(--action-button-deemphasized-fill-color-pressed-active);
|
fill: var(--action-button-deemphasized-fill-color-pressed-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* disable the separate press color (noPressColor)
|
||||||
|
*/
|
||||||
|
.icon-button.pressed.no-press-color .icon-button-svg {
|
||||||
|
fill: var(--action-button-fill-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button.pressed.no-press-color:hover .icon-button-svg {
|
||||||
|
fill: var(--action-button-fill-color-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button.pressed.no-press-color:active .icon-button-svg {
|
||||||
|
fill: var(--action-button-fill-color-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import { classname } from '../_utils/classname'
|
import { classname } from '../_utils/classname'
|
||||||
|
@ -114,17 +130,19 @@
|
||||||
pressable: false,
|
pressable: false,
|
||||||
pressed: false,
|
pressed: false,
|
||||||
className: void 0,
|
className: void 0,
|
||||||
delegateKey: void 0
|
delegateKey: void 0,
|
||||||
|
noPressColor: false
|
||||||
}),
|
}),
|
||||||
store: () => store,
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
computedClass: ({ pressable, pressed, big, muted, className }) => {
|
computedClass: ({ pressable, pressed, big, muted, noPressColor, className }) => {
|
||||||
return classname(
|
return classname(
|
||||||
'icon-button',
|
'icon-button',
|
||||||
!pressable && 'not-pressable',
|
!pressable && 'not-pressable',
|
||||||
pressed && 'pressed',
|
pressed && 'pressed',
|
||||||
big && 'big-icon',
|
big && 'big-icon',
|
||||||
muted && 'muted-style',
|
muted && 'muted-style',
|
||||||
|
noPressColor && 'no-press-color',
|
||||||
className
|
className
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,37 @@
|
||||||
|
const getDefault = mod => mod.default
|
||||||
|
|
||||||
export const importShowAccountProfileOptionsDialog = () => import(
|
export const importShowAccountProfileOptionsDialog = () => import(
|
||||||
/* webpackChunkName: 'showAccountProfileOptionsDialog' */ './creators/showAccountProfileOptionsDialog'
|
/* webpackChunkName: 'showAccountProfileOptionsDialog' */ './creators/showAccountProfileOptionsDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowComposeDialog = () => import(
|
export const importShowComposeDialog = () => import(
|
||||||
/* webpackChunkName: 'showComposeDialog' */ './creators/showComposeDialog'
|
/* webpackChunkName: 'showComposeDialog' */ './creators/showComposeDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowConfirmationDialog = () => import(
|
export const importShowConfirmationDialog = () => import(
|
||||||
/* webpackChunkName: 'showConfirmationDialog' */ './creators/showConfirmationDialog'
|
/* webpackChunkName: 'showConfirmationDialog' */ './creators/showConfirmationDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowEmojiDialog = () => import(
|
export const importShowEmojiDialog = () => import(
|
||||||
/* webpackChunkName: 'showEmojiDialog' */ './creators/showEmojiDialog'
|
/* webpackChunkName: 'showEmojiDialog' */ './creators/showEmojiDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowImageDialog = () => import(
|
|
||||||
/* webpackChunkName: 'showImageDialog' */ './creators/showImageDialog'
|
|
||||||
).then(mod => mod.default)
|
|
||||||
|
|
||||||
export const importShowPostPrivacyDialog = () => import(
|
export const importShowPostPrivacyDialog = () => import(
|
||||||
/* webpackChunkName: 'showPostPrivacyDialog' */ './creators/showPostPrivacyDialog'
|
/* webpackChunkName: 'showPostPrivacyDialog' */ './creators/showPostPrivacyDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowStatusOptionsDialog = () => import(
|
export const importShowStatusOptionsDialog = () => import(
|
||||||
/* webpackChunkName: 'showStatusOptionsDialog' */ './creators/showStatusOptionsDialog'
|
/* webpackChunkName: 'showStatusOptionsDialog' */ './creators/showStatusOptionsDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowVideoDialog = () => import(
|
|
||||||
/* webpackChunkName: 'showVideoDialog' */ './creators/showVideoDialog'
|
|
||||||
).then(mod => mod.default)
|
|
||||||
|
|
||||||
export const importShowCopyDialog = () => import(
|
export const importShowCopyDialog = () => import(
|
||||||
/* webpackChunkName: 'showCopyDialog' */ './creators/showCopyDialog'
|
/* webpackChunkName: 'showCopyDialog' */ './creators/showCopyDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importShowShortcutHelpDialog = () => import(
|
export const importShowShortcutHelpDialog = () => import(
|
||||||
/* webpackChunkName: 'showShortcutHelpDialog' */ './creators/showShortcutHelpDialog'
|
/* webpackChunkName: 'showShortcutHelpDialog' */ './creators/showShortcutHelpDialog'
|
||||||
).then(mod => mod.default)
|
).then(getDefault)
|
||||||
|
|
||||||
|
export const importShowMediaDialog = () => import(
|
||||||
|
/* webpackChunkName: 'showMediaDialog' */ './creators/showMediaDialog'
|
||||||
|
).then(getDefault)
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
<ModalDialog
|
|
||||||
{id}
|
|
||||||
{label}
|
|
||||||
background="var(--muted-modal-bg)"
|
|
||||||
muted="true"
|
|
||||||
className="image-modal-dialog"
|
|
||||||
>
|
|
||||||
{#if type === 'gifv'}
|
|
||||||
<video
|
|
||||||
class="image-modal-dialog-autoplay-video"
|
|
||||||
aria-label="Animated GIF: {description || ''}"
|
|
||||||
style="{videoStyle}"
|
|
||||||
{src}
|
|
||||||
autoplay
|
|
||||||
muted
|
|
||||||
loop
|
|
||||||
webkit-playsinline
|
|
||||||
playsinline
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<img
|
|
||||||
{src}
|
|
||||||
{style}
|
|
||||||
alt={description || ''}
|
|
||||||
title={description || ''}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</ModalDialog>
|
|
||||||
<style>
|
|
||||||
:global(.image-modal-dialog img, .image-modal-dialog video) {
|
|
||||||
object-fit: contain;
|
|
||||||
max-width: calc(100vw - 20px);
|
|
||||||
max-height: calc(100% - 20px);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-modal-dialog-autoplay-video {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
background-size: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
import ModalDialog from './ModalDialog.html'
|
|
||||||
import { show } from '../helpers/showDialog'
|
|
||||||
import { oncreate } from '../helpers/onCreateDialog'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
oncreate,
|
|
||||||
components: {
|
|
||||||
ModalDialog
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
style: ({ width, height }) => `
|
|
||||||
width: ${width ? width + 'px' : 'auto'};
|
|
||||||
height: ${height ? height + 'px' : 'auto'};`,
|
|
||||||
videoStyle: ({ style, poster }) => `
|
|
||||||
${style}
|
|
||||||
background-image: url(${poster});`
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
show
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
214
src/routes/_components/dialog/components/MediaDialog.html
Normal file
214
src/routes/_components/dialog/components/MediaDialog.html
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
<ModalDialog
|
||||||
|
{id}
|
||||||
|
{label}
|
||||||
|
background="var(--muted-modal-bg)"
|
||||||
|
muted="true"
|
||||||
|
className="media-modal-dialog"
|
||||||
|
>
|
||||||
|
<div class="media-container">
|
||||||
|
<div class="media-scroll" ref:scroller>
|
||||||
|
{#each mediaItems as media}
|
||||||
|
<div class="media-scroll-item">
|
||||||
|
<div class="media-scroll-item-inner">
|
||||||
|
<div class="media-scroll-item-inner-inner">
|
||||||
|
<MediaInDialog {media} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{#if dots.length > 1}
|
||||||
|
<div class="media-controls">
|
||||||
|
<IconButton
|
||||||
|
className="media-control-button"
|
||||||
|
disabled={scrolledItem === 0}
|
||||||
|
label="Show previous media"
|
||||||
|
href="#fa-angle-left"
|
||||||
|
on:click="onClick(scrolledItem - 1)"
|
||||||
|
/>
|
||||||
|
{#each dots as dot, i (dot.i)}
|
||||||
|
<IconButton
|
||||||
|
className="media-control-button"
|
||||||
|
pressable={true}
|
||||||
|
label="Show {nth(i)} media"
|
||||||
|
pressed={i === scrolledItem}
|
||||||
|
href={i === scrolledItem ? '#fa-circle' : '#fa-circle-o'}
|
||||||
|
noPressColor={true}
|
||||||
|
on:click="onClick(i)"
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
<IconButton
|
||||||
|
className="media-control-button"
|
||||||
|
disabled={scrolledItem === length - 1}
|
||||||
|
label="Show next media"
|
||||||
|
href="#fa-angle-right"
|
||||||
|
on:click="onClick(scrolledItem + 1)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</ModalDialog>
|
||||||
|
<style>
|
||||||
|
:global(.media-modal-dialog) {
|
||||||
|
max-width: calc(100vw);
|
||||||
|
}
|
||||||
|
.media-container {
|
||||||
|
height: calc(100% - 64px); /* 44px X button height + 20px padding */
|
||||||
|
width: calc(100vw);
|
||||||
|
padding-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.media-scroll {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-scroll::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-scroll-item {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.media-scroll-item-inner {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.media-scroll-item-inner-inner {
|
||||||
|
height: calc(100% - 10px);
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 10px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.media-control-button) {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (scroll-snap-align: start) {
|
||||||
|
/* modern scroll snap points */
|
||||||
|
.media-scroll {
|
||||||
|
scroll-snap-type: x mandatory;
|
||||||
|
}
|
||||||
|
.media-scroll-item {
|
||||||
|
scroll-snap-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@supports not (scroll-snap-align: start) {
|
||||||
|
/* old scroll snap points spec */
|
||||||
|
.media-scroll {
|
||||||
|
-webkit-scroll-snap-type: mandatory;
|
||||||
|
scroll-snap-type: mandatory;
|
||||||
|
-webkit-scroll-snap-destination: 0% center;
|
||||||
|
scroll-snap-destination: 0% center;
|
||||||
|
-webkit-scroll-snap-points-x: repeat(100%);
|
||||||
|
scroll-snap-points-x: repeat(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
import ModalDialog from './ModalDialog.html'
|
||||||
|
import MediaInDialog from './MediaInDialog.html'
|
||||||
|
import IconButton from '../../IconButton.html'
|
||||||
|
import { show } from '../helpers/showDialog'
|
||||||
|
import { oncreate as onCreateDialog } from '../helpers/onCreateDialog'
|
||||||
|
import debounce from 'lodash-es/debounce'
|
||||||
|
import times from 'lodash-es/times'
|
||||||
|
import { smoothScroll } from '../../../_utils/smoothScroll'
|
||||||
|
import { doubleRAF } from '../../../_utils/doubleRAF'
|
||||||
|
import { store } from '../../../_store/store'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
oncreate () {
|
||||||
|
onCreateDialog.call(this)
|
||||||
|
|
||||||
|
this.onScroll = debounce(this.onScroll.bind(this), 100, { leading: false, trailing: true })
|
||||||
|
|
||||||
|
let { scrolledItem } = this.get()
|
||||||
|
if (scrolledItem) {
|
||||||
|
doubleRAF(() => {
|
||||||
|
this.scrollToItem(scrolledItem, false)
|
||||||
|
this.setupScroll()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setupScroll()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ondestroy () {
|
||||||
|
this.teardownScroll()
|
||||||
|
},
|
||||||
|
store: () => store,
|
||||||
|
computed: {
|
||||||
|
length: ({ mediaItems }) => mediaItems.length,
|
||||||
|
originalWidths: ({ mediaItems }) => mediaItems.map(_ => _.meta.original.width),
|
||||||
|
maxWidth: ({ originalWidths }) => Math.max.apply(Math, originalWidths),
|
||||||
|
dots: ({ length }) => times(length, i => ({ i }))
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ModalDialog,
|
||||||
|
MediaInDialog,
|
||||||
|
IconButton
|
||||||
|
},
|
||||||
|
helpers: {
|
||||||
|
nth (i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return 'first'
|
||||||
|
case 1:
|
||||||
|
return 'second'
|
||||||
|
case 2:
|
||||||
|
return 'third'
|
||||||
|
case 3:
|
||||||
|
return 'fourth'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show,
|
||||||
|
setupScroll () {
|
||||||
|
this.refs.scroller.addEventListener('scroll', this.onScroll)
|
||||||
|
},
|
||||||
|
teardownScroll () {
|
||||||
|
this.refs.scroller.removeEventListener('scroll', this.onScroll)
|
||||||
|
},
|
||||||
|
onScroll () {
|
||||||
|
let { length } = this.get()
|
||||||
|
let { scrollWidth, scrollLeft } = this.refs.scroller
|
||||||
|
let scrolledItem = Math.floor((scrollLeft / scrollWidth) * length)
|
||||||
|
this.set({ scrolledItem })
|
||||||
|
},
|
||||||
|
onClick (i) {
|
||||||
|
let { scrolledItem } = this.get()
|
||||||
|
if (scrolledItem !== i) {
|
||||||
|
this.scrollToItem(i, true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scrollToItem (i, smooth) {
|
||||||
|
let { length } = this.get()
|
||||||
|
let { scroller } = this.refs
|
||||||
|
let { scrollWidth } = scroller
|
||||||
|
let scrollLeft = Math.floor(scrollWidth * (i / length))
|
||||||
|
if (smooth) {
|
||||||
|
smoothScroll(scroller, scrollLeft, true)
|
||||||
|
} else {
|
||||||
|
scroller.scrollLeft = scrollLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
52
src/routes/_components/dialog/components/MediaInDialog.html
Normal file
52
src/routes/_components/dialog/components/MediaInDialog.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{#if type === 'video'}
|
||||||
|
<video
|
||||||
|
class="media-fit"
|
||||||
|
aria-label={description}
|
||||||
|
src={url}
|
||||||
|
{poster}
|
||||||
|
controls
|
||||||
|
ref:video
|
||||||
|
/>
|
||||||
|
{:elseif type === 'gifv'}
|
||||||
|
<video
|
||||||
|
class="media-fit"
|
||||||
|
style="background-image:url({static_url});"
|
||||||
|
aria-label={description}
|
||||||
|
src={url}
|
||||||
|
autoplay
|
||||||
|
muted
|
||||||
|
loop
|
||||||
|
webkit-playsinline
|
||||||
|
playsinline
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<img
|
||||||
|
class="media-fit"
|
||||||
|
alt={description}
|
||||||
|
title={description}
|
||||||
|
src={url}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
<style>
|
||||||
|
.media-fit {
|
||||||
|
object-fit: contain;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
type: ({ media }) => media.type,
|
||||||
|
url: ({ media }) => media.url,
|
||||||
|
description: ({ media }) => media.description || '',
|
||||||
|
poster: ({ media }) => media.poster,
|
||||||
|
static_url: ({ media }) => media.static_url
|
||||||
|
},
|
||||||
|
ondestroy () {
|
||||||
|
if (this.refs.video && !this.refs.video.paused) {
|
||||||
|
this.refs.video.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,49 +0,0 @@
|
||||||
<ModalDialog
|
|
||||||
{id}
|
|
||||||
{label}
|
|
||||||
background="var(--muted-modal-bg)"
|
|
||||||
muted="true"
|
|
||||||
className="video-modal-dialog"
|
|
||||||
on:close="onClose()"
|
|
||||||
>
|
|
||||||
<video {poster}
|
|
||||||
{src}
|
|
||||||
{style}
|
|
||||||
aria-label="Video: {description || ''}"
|
|
||||||
controls
|
|
||||||
ref:video
|
|
||||||
/>
|
|
||||||
</ModalDialog>
|
|
||||||
<style>
|
|
||||||
:global(.video-modal-dialog video) {
|
|
||||||
object-fit: contain;
|
|
||||||
max-width: calc(100vw - 20px);
|
|
||||||
max-height: calc(100% - 20px);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
import ModalDialog from './ModalDialog.html'
|
|
||||||
import { show } from '../helpers/showDialog'
|
|
||||||
import { oncreate } from '../helpers/onCreateDialog'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
oncreate,
|
|
||||||
components: {
|
|
||||||
ModalDialog
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
style: ({ width, height }) => `
|
|
||||||
width: ${width ? width + 'px' : 'auto'};
|
|
||||||
height: ${height ? height + 'px' : 'auto'};`
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
show,
|
|
||||||
onClose () {
|
|
||||||
if (this.refs.video && !this.refs.video.paused) {
|
|
||||||
this.refs.video.pause()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,20 +0,0 @@
|
||||||
import ImageDialog from '../components/ImageDialog.html'
|
|
||||||
import { createDialogElement } from '../helpers/createDialogElement'
|
|
||||||
import { createDialogId } from '../helpers/createDialogId'
|
|
||||||
|
|
||||||
export default function showImageDialog (poster, src, type, width, height, description) {
|
|
||||||
let imageDialog = new ImageDialog({
|
|
||||||
target: createDialogElement(),
|
|
||||||
data: {
|
|
||||||
id: createDialogId(),
|
|
||||||
label: 'Image dialog',
|
|
||||||
poster,
|
|
||||||
src,
|
|
||||||
type,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
description
|
|
||||||
}
|
|
||||||
})
|
|
||||||
imageDialog.show()
|
|
||||||
}
|
|
16
src/routes/_components/dialog/creators/showMediaDialog.js
Normal file
16
src/routes/_components/dialog/creators/showMediaDialog.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import MediaDialog from '../components/MediaDialog.html'
|
||||||
|
import { createDialogElement } from '../helpers/createDialogElement'
|
||||||
|
import { createDialogId } from '../helpers/createDialogId'
|
||||||
|
|
||||||
|
export default function showMediaDialog (mediaItems, scrolledItem) {
|
||||||
|
let dialog = new MediaDialog({
|
||||||
|
target: createDialogElement(),
|
||||||
|
data: {
|
||||||
|
id: createDialogId(),
|
||||||
|
label: 'Media dialog',
|
||||||
|
mediaItems,
|
||||||
|
scrolledItem
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dialog.show()
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
import VideoDialog from '../components/VideoDialog.html'
|
|
||||||
import { createDialogElement } from '../helpers/createDialogElement'
|
|
||||||
import { createDialogId } from '../helpers/createDialogId'
|
|
||||||
|
|
||||||
export default function showVideoDialog (poster, src, width, height, description) {
|
|
||||||
let videoDialog = new VideoDialog({
|
|
||||||
target: createDialogElement(),
|
|
||||||
data: {
|
|
||||||
id: createDialogId(),
|
|
||||||
label: 'Video dialog',
|
|
||||||
poster,
|
|
||||||
src,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
description
|
|
||||||
}
|
|
||||||
})
|
|
||||||
videoDialog.show()
|
|
||||||
}
|
|
|
@ -79,7 +79,7 @@
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT, ONE_TRANSPARENT_PIXEL } from '../../_static/media'
|
import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT, ONE_TRANSPARENT_PIXEL } from '../../_static/media'
|
||||||
import { importShowVideoDialog, importShowImageDialog } from '../dialog/asyncDialogs'
|
import { importShowMediaDialog } from '../dialog/asyncDialogs'
|
||||||
import { mouseover } from '../../_utils/events'
|
import { mouseover } from '../../_utils/events'
|
||||||
import NonAutoplayGifv from '../NonAutoplayGifv.html'
|
import NonAutoplayGifv from '../NonAutoplayGifv.html'
|
||||||
import PlayVideoIcon from '../PlayVideoIcon.html'
|
import PlayVideoIcon from '../PlayVideoIcon.html'
|
||||||
|
@ -91,14 +91,7 @@
|
||||||
export default {
|
export default {
|
||||||
oncreate () {
|
oncreate () {
|
||||||
let { delegateKey } = this.get()
|
let { delegateKey } = this.get()
|
||||||
registerClickDelegate(this, delegateKey, () => {
|
registerClickDelegate(this, delegateKey, () => this.onClick())
|
||||||
let { type } = this.get()
|
|
||||||
if (type === 'video') {
|
|
||||||
this.onClickPlayVideoButton()
|
|
||||||
} else {
|
|
||||||
this.onClickShowImageButton()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
focus: ({ meta }) => meta && meta.focus,
|
focus: ({ meta }) => meta && meta.focus,
|
||||||
|
@ -133,17 +126,10 @@
|
||||||
type: ({ media }) => media.type
|
type: ({ media }) => media.type
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onClickPlayVideoButton () {
|
async onClick () {
|
||||||
let { previewUrl, url, modalWidth, modalHeight, description } = this.get()
|
let { mediaAttachments, index } = this.get()
|
||||||
let showVideoDialog = await importShowVideoDialog()
|
let showMediaDialog = await importShowMediaDialog()
|
||||||
showVideoDialog(previewUrl, url,
|
showMediaDialog(mediaAttachments, index)
|
||||||
modalWidth, modalHeight, description)
|
|
||||||
},
|
|
||||||
async onClickShowImageButton () {
|
|
||||||
let { previewUrl, url, modalWidth, modalHeight, description, type } = this.get()
|
|
||||||
let showImageDialog = await importShowImageDialog()
|
|
||||||
showImageDialog(previewUrl, url, type,
|
|
||||||
modalWidth, modalHeight, description)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class={computedClass}
|
<div class={computedClass}
|
||||||
style="grid-template-columns: repeat({nCols}, 1fr);" >
|
style="grid-template-columns: repeat({nCols}, 1fr);" >
|
||||||
{#each mediaAttachments as media}
|
{#each mediaAttachments as media, index}
|
||||||
<Media {media} {uuid} />
|
<Media {media} {uuid} {mediaAttachments} {index} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -61,13 +61,13 @@ function testSupportsSmoothScroll () {
|
||||||
|
|
||||||
const smoothScrollSupported = process.browser && testSupportsSmoothScroll()
|
const smoothScrollSupported = process.browser && testSupportsSmoothScroll()
|
||||||
|
|
||||||
export function smoothScroll (node, top) {
|
export function smoothScroll (node, topOrLeft, horizontal) {
|
||||||
if (smoothScrollSupported) {
|
if (smoothScrollSupported) {
|
||||||
return node.scrollTo({
|
return node.scrollTo({
|
||||||
top: top,
|
[horizontal ? 'left' : 'top']: topOrLeft,
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return smoothScrollPolyfill(node, 'scrollTop', top)
|
return smoothScrollPolyfill(node, horizontal ? 'scrollLeft' : 'scrollTop', topOrLeft)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue