diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 14ae19d404..992d7129d7 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -11,27 +11,62 @@ const MediaModal = { showing () { return this.$store.state.mediaViewer.activated }, + media () { + return this.$store.state.mediaViewer.media + }, currentIndex () { return this.$store.state.mediaViewer.currentIndex }, currentMedia () { - return this.$store.state.mediaViewer.media[this.currentIndex] + return this.media[this.currentIndex] + }, + canNavigate () { + return this.media.length > 1 }, type () { return this.currentMedia ? fileTypeService.fileType(this.currentMedia.mimetype) : null } }, - created () { - document.addEventListener('keyup', e => { - if (e.keyCode === 27 && this.showing) { // escape - this.hide() - } - }) - }, methods: { hide () { this.$store.dispatch('closeMediaViewer') + }, + goPrev () { + if (this.canNavigate) { + const prevIndex = this.currentIndex === 0 ? this.media.length - 1 : (this.currentIndex - 1) + this.$store.dispatch('setCurrent', this.media[prevIndex]) + } + }, + goNext () { + if (this.canNavigate) { + const nextIndex = this.currentIndex === this.media.length - 1 ? 0 : (this.currentIndex + 1) + this.$store.dispatch('setCurrent', this.media[nextIndex]) + } + }, + 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 () { + document.addEventListener('keyup', this.handleKeyupEvent) + document.addEventListener('keydown', this.handleKeydownEvent) + }, + destroyed () { + document.removeEventListener('keyup', this.handleKeyupEvent) + document.removeEventListener('keydown', this.handleKeydownEvent) } } diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 796d4e403a..427bf12b06 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -8,6 +8,22 @@ :controls="true" @click.stop.native=""> + + @@ -19,15 +35,29 @@ .modal-view { z-index: 1000; position: fixed; - width: 100vw; - height: 100vh; top: 0; left: 0; + right: 0; + bottom: 0; display: flex; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.5); - cursor: pointer; + + &:hover { + .modal-view-button-arrow { + opacity: 0.75; + + &:focus, + &:hover { + outline: none; + box-shadow: none; + } + &:hover { + opacity: 1; + } + } + } } .modal-image { @@ -35,4 +65,49 @@ max-height: 90%; box-shadow: 0px 5px 15px 0 rgba(0, 0, 0, 0.5); } + +.modal-view-button-arrow { + position: absolute; + display: block; + top: 50%; + margin-top: -50px; + width: 70px; + height: 100px; + border: 0; + padding: 0; + opacity: 0; + box-shadow: none; + background: none; + appearance: none; + overflow: visible; + cursor: pointer; + transition: opacity 333ms cubic-bezier(.4,0,.22,1); + + .arrow-icon { + position: absolute; + top: 35px; + height: 30px; + width: 32px; + font-size: 14px; + line-height: 30px; + color: #FFF; + text-align: center; + background-color: rgba(0,0,0,.3); + } + + &--prev { + left: 0; + .arrow-icon { + left: 6px; + } + } + + &--next { + right: 0; + .arrow-icon { + right: 6px; + } + } +} + diff --git a/src/i18n/en.json b/src/i18n/en.json index 2067e6db87..78e8fced69 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -36,6 +36,10 @@ "username": "Username", "hint": "Log in to join the discussion" }, + "media_modal": { + "previous": "Previous", + "next": "Next" + }, "nav": { "about": "About", "back": "Back",