import StillImage from '../still-image/still-image.vue' import VideoAttachment from '../video_attachment/video_attachment.vue' import Modal from '../modal/modal.vue' import PinchZoom from '../pinch_zoom/pinch_zoom.vue' import SwipeClick from '../swipe_click/swipe_click.vue' import GestureService from '../../services/gesture_service/gesture_service' import Flash from 'src/components/flash/flash.vue' import fileTypeService from '../../services/file_type/file_type.service.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronLeft, faChevronRight, faCircleNotch, faTimes } from '@fortawesome/free-solid-svg-icons' library.add( faChevronLeft, faChevronRight, faCircleNotch, faTimes ) const MediaModal = { components: { StillImage, VideoAttachment, PinchZoom, SwipeClick, Modal, Flash }, data () { return { loading: false, swipeDirection: GestureService.DIRECTION_LEFT, swipeThreshold: () => { const considerableMoveRatio = 1 / 4 return window.innerWidth * considerableMoveRatio }, pinchZoomMinScale: 1, pinchZoomScaleResetLimit: 1.2 } }, computed: { showing () { return this.$store.state.mediaViewer.activated }, media () { return this.$store.state.mediaViewer.media }, description () { return this.currentMedia.description }, currentIndex () { return this.$store.state.mediaViewer.currentIndex }, currentMedia () { return this.media[this.currentIndex] }, canNavigate () { return this.media.length > 1 }, type () { return this.currentMedia ? this.getType(this.currentMedia) : null } }, methods: { getType (media) { return fileTypeService.fileType(media.mimetype) }, hide () { // HACK: Closing immediately via a touch will cause the click // to be processed on the content below the overlay const transitionTime = 100 // ms setTimeout(() => { this.$store.dispatch('closeMediaViewer') }, transitionTime) }, hideIfNotSwiped (event) { // If we have swiped over SwipeClick, do not trigger hide const comp = this.$refs.swipeClick if (!comp) { this.hide() } else { comp.$gesture.click(event) } }, goPrev () { if (this.canNavigate) { const prevIndex = this.currentIndex === 0 ? this.media.length - 1 : (this.currentIndex - 1) const newMedia = this.media[prevIndex] if (this.getType(newMedia) === 'image') { this.loading = true } this.$store.dispatch('setCurrentMedia', newMedia) } }, goNext () { if (this.canNavigate) { const nextIndex = this.currentIndex === this.media.length - 1 ? 0 : (this.currentIndex + 1) const newMedia = this.media[nextIndex] if (this.getType(newMedia) === 'image') { this.loading = true } this.$store.dispatch('setCurrentMedia', newMedia) } }, onImageLoaded () { this.loading = false }, handleSwipePreview (offsets) { this.$refs.pinchZoom.setTransform({ scale: 1, x: offsets[0], y: 0 }) }, handleSwipeEnd (sign) { this.$refs.pinchZoom.setTransform({ scale: 1, x: 0, y: 0 }) if (sign > 0) { this.goNext() } else if (sign < 0) { this.goPrev() } }, handleKeyupEvent (e) { if (this.showing && e.keyCode === 27) { // escape this.hide() } }, handleKeydownEvent (e) { if (!this.showing) { return } if (e.keyCode === 39) { // arrow right this.goNext() } else if (e.keyCode === 37) { // arrow left this.goPrev() } } }, mounted () { window.addEventListener('popstate', this.hide) document.addEventListener('keyup', this.handleKeyupEvent) document.addEventListener('keydown', this.handleKeydownEvent) }, unmounted () { window.removeEventListener('popstate', this.hide) document.removeEventListener('keyup', this.handleKeyupEvent) document.removeEventListener('keydown', this.handleKeydownEvent) } } export default MediaModal