From f96e5882d16a8662ceb7b8cc6aa36fe131a2682f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 1 Aug 2021 13:39:56 -0400 Subject: Make media modal be aware of multi-touch actions Originally the media viewer would think every touch is a swipe (one-finger touch event), so we would encounter the case where a two-finger scale event would incorrectly change the current media. This is now fixed. --- src/components/media_modal/media_modal.vue | 1 + 1 file changed, 1 insertion(+) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 8680267b..b5a65d50 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -13,6 +13,7 @@ :title="currentMedia.description" @touchstart.stop="mediaTouchStart" @touchmove.stop="mediaTouchMove" + @touchend.stop="mediaTouchEnd" @click="hide" @load="onImageLoaded" > -- cgit v1.2.3-70-g09d2 From a7570f5eb2b8bc576edbcc8e212b2c873ac99e7e Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 1 Aug 2021 19:46:27 -0400 Subject: Preview swipe action --- src/components/media_modal/media_modal.js | 26 +++++++++ src/components/media_modal/media_modal.vue | 1 + src/modules/media_viewer.js | 64 +++++++++++++++++++++- src/services/gesture_service/gesture_service.js | 73 +++++++++++++++++-------- 4 files changed, 138 insertions(+), 26 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index f3d381ee..8f67db2b 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -4,6 +4,7 @@ import Modal from '../modal/modal.vue' import fileTypeService from '../../services/file_type/file_type.service.js' import GestureService from '../../services/gesture_service/gesture_service' import Flash from 'src/components/flash/flash.vue' +import Vuex from 'vuex' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronLeft, @@ -17,6 +18,8 @@ library.add( faCircleNotch ) +const onlyXAxis = ([x, y]) => [x, 0] + const MediaModal = { components: { StillImage, @@ -50,6 +53,15 @@ const MediaModal = { }, type () { return this.currentMedia ? this.getType(this.currentMedia) : null + }, + scaling () { + return this.$store.state.mediaViewer.swipeScaler.scaling + }, + offsets () { + return this.$store.state.mediaViewer.swipeScaler.offsets + }, + transform () { + return `scale(${this.scaling}, ${this.scaling}) translate(${this.offsets[0]}px, ${this.offsets[1]}px)` } }, created () { @@ -57,6 +69,8 @@ const MediaModal = { direction: GestureService.DIRECTION_LEFT, callbackPositive: this.goNext, callbackNegative: this.goPrev, + swipePreviewCallback: this.handleSwipePreview, + swipeEndCallback: this.handleSwipeEnd, threshold: 50 }) }, @@ -99,6 +113,18 @@ const MediaModal = { onImageLoaded () { this.loading = false }, + handleSwipePreview (offsets) { + this.$store.dispatch('swipeScaler/apply', { offsets: onlyXAxis(offsets) }) + }, + handleSwipeEnd (sign) { + if (sign === 0) { + this.$store.dispatch('swipeScaler/revert') + } else if (sign > 0) { + this.goNext() + } else { + this.goPrev() + } + }, handleKeyupEvent (e) { if (this.showing && e.keyCode === 27) { // escape this.hide() diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index b5a65d50..728c3035 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -11,6 +11,7 @@ :src="currentMedia.url" :alt="currentMedia.description" :title="currentMedia.description" + :style="{ transform }" @touchstart.stop="mediaTouchStart" @touchmove.stop="mediaTouchMove" @touchend.stop="mediaTouchEnd" diff --git a/src/modules/media_viewer.js b/src/modules/media_viewer.js index ebcba01d..38723763 100644 --- a/src/modules/media_viewer.js +++ b/src/modules/media_viewer.js @@ -20,19 +20,79 @@ const mediaViewer = { } }, actions: { - setMedia ({ commit }, attachments) { + setMedia ({ commit, dispatch }, attachments) { const media = attachments.filter(attachment => { const type = fileTypeService.fileType(attachment.mimetype) return supportedTypes.has(type) }) commit('setMedia', media) + dispatch('swipeScaler/reset') }, setCurrentMedia ({ commit, state }, current) { const index = state.media.indexOf(current) commit('setCurrentMedia', index || 0) + dispatch('swipeScaler/reset') }, - closeMediaViewer ({ commit }) { + closeMediaViewer ({ commit, dispatch }) { commit('close') + dispatch('swipeScaler/reset') + } + }, + modules: { + swipeScaler: { + namespaced: true, + + state: { + origOffsets: [0, 0], + offsets: [0, 0], + origScaling: 1, + scaling: 1 + }, + + mutations: { + reset (state) { + state.origOffsets = [0, 0] + state.offsets = [0, 0] + state.origScaling = 1 + state.scaling = 1 + }, + applyOffsets (state, { offsets }) { + state.offsets = state.origOffsets.map((k, n) => k + offsets[n]) + }, + applyScaling (state, { scaling }) { + state.scaling = state.origScaling * scaling + }, + finishOffsets (state) { + state.origOffsets = [...state.offsets] + }, + finishScaling (state) { + state.origScaling = state.scaling + }, + revertOffsets (state) { + state.offsets = [...state.origOffsets] + }, + revertScaling (state) { + state.scaling = state.origScaling + } + }, + + actions: { + reset ({ commit }) { + commit('reset') + }, + apply ({ commit }, { offsets, scaling = 1 }) { + commit('applyOffsets', { offsets }) + commit('applyScaling', { scaling }) + }, + finish ({ commit }) { + commit('finishOffsets') + commit('finishScaling') + }, + revert ({ commit }) { + commit('revertOffsets') + commit('revertScaling') + } + } } } } diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index 8df4f03d..8f406762 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -70,14 +70,28 @@ const updateSwipe = (event, gesture) => { } class SwipeAndScaleGesture { + // swipePreviewCallback(offsets: Array[Number]) + // offsets: the offset vector which the underlying component should move, from the starting position + // pinchPreviewCallback(offsets: Array[Number], scaling: Number) + // offsets: the offset vector which the underlying component should move, from the starting position + // scaling: the scaling factor we should apply to the underlying component, from the starting position + // swipeEndcallback(sign: 0|-1|1) + // sign: if the swipe does not meet the threshold, 0 + // if the swipe meets the threshold in the positive direction, 1 + // if the swipe meets the threshold in the negative direction, -1 constructor ({ - direction, callbackPositive, callbackNegative, - previewCallback, threshold = 30, perpendicularTolerance = 1.0 + direction, + // swipeStartCallback, pinchStartCallback, + swipePreviewCallback, pinchPreviewCallback, + swipeEndCallback, pinchEndCallback, + threshold = 30, perpendicularTolerance = 1.0 }) { + const nop = () => {} this.direction = direction - this.previewCallback = previewCallback - this.callbackPositive = callbackPositive - this.callbackNegative = callbackNegative + this.swipePreviewCallback = swipePreviewCallback || nop + this.pinchPreviewCallback = pinchPreviewCallback || nop + this.swipeEndCallback = swipeEndCallback || nop + this.pinchEndCallback = pinchEndCallback || nop this.threshold = threshold this.perpendicularTolerance = perpendicularTolerance this._startPos = [0, 0] @@ -97,7 +111,12 @@ class SwipeAndScaleGesture { } move (event) { - if (isScaleEvent(event)) { + if (isSwipeEvent(event)) { + const touch = event.changedTouches[0] + const delta = deltaCoord(this._startPos, touchCoord(touch)) + + this.swipePreviewCallback(delta) + } else if (isScaleEvent(event)) { } } @@ -118,24 +137,30 @@ class SwipeAndScaleGesture { // movement too small const touch = event.changedTouches[0] const delta = deltaCoord(this._startPos, touchCoord(touch)) - if (vectorLength(delta) < this.threshold) return - // movement is opposite from direction - const isPositive = dotProduct(delta, this.direction) > 0 - - // movement perpendicular to direction is too much - const towardsDir = project(delta, this.direction) - const perpendicularDir = perpendicular(this.direction) - const towardsPerpendicular = project(delta, perpendicularDir) - if ( - vectorLength(towardsDir) * this.perpendicularTolerance < - vectorLength(towardsPerpendicular) - ) return - - if (isPositive) { - this.callbackPositive() - } else { - this.callbackNegative() - } + this.swipePreviewCallback(delta) + + const sign = (() => { + if (vectorLength(delta) < this.threshold) { + return 0 + } + // movement is opposite from direction + const isPositive = dotProduct(delta, this.direction) > 0 + + // movement perpendicular to direction is too much + const towardsDir = project(delta, this.direction) + const perpendicularDir = perpendicular(this.direction) + const towardsPerpendicular = project(delta, perpendicularDir) + if ( + vectorLength(towardsDir) * this.perpendicularTolerance < + vectorLength(towardsPerpendicular) + ) { + return 0 + } + + return isPositive ? 1 : -1 + })() + + this.swipeEndCallback(sign) } } -- cgit v1.2.3-70-g09d2 From d9030b4fddc9f47cb2f16a7a65f57a5703059e3f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 1 Aug 2021 21:39:07 -0400 Subject: Handle pinch action --- src/components/media_modal/media_modal.js | 11 ++++++- src/components/media_modal/media_modal.vue | 6 ++-- src/modules/media_viewer.js | 14 +++------ src/services/gesture_service/gesture_service.js | 42 +++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 16 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 8f67db2b..04dd8658 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -61,7 +61,7 @@ const MediaModal = { return this.$store.state.mediaViewer.swipeScaler.offsets }, transform () { - return `scale(${this.scaling}, ${this.scaling}) translate(${this.offsets[0]}px, ${this.offsets[1]}px)` + return `translate(${this.offsets[0]}px, ${this.offsets[1]}px) scale(${this.scaling}, ${this.scaling})` } }, created () { @@ -71,6 +71,8 @@ const MediaModal = { callbackNegative: this.goPrev, swipePreviewCallback: this.handleSwipePreview, swipeEndCallback: this.handleSwipeEnd, + pinchPreviewCallback: this.handlePinchPreview, + pinchEndCallback: this.handlePinchEnd, threshold: 50 }) }, @@ -125,6 +127,13 @@ const MediaModal = { this.goPrev() } }, + handlePinchPreview (offsets, scaling) { + console.log('handle pinch preview:', offsets, scaling) + this.$store.dispatch('swipeScaler/apply', { offsets, scaling }) + }, + handlePinchEnd () { + this.$store.dispatch('swipeScaler/finish') + }, handleKeyupEvent (e) { if (this.showing && e.keyCode === 27) { // escape this.hide() diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 728c3035..853dec1d 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -12,9 +12,9 @@ :alt="currentMedia.description" :title="currentMedia.description" :style="{ transform }" - @touchstart.stop="mediaTouchStart" - @touchmove.stop="mediaTouchMove" - @touchend.stop="mediaTouchEnd" + @touchstart.stop.prevent="mediaTouchStart" + @touchmove.stop.prevent="mediaTouchMove" + @touchend.stop.prevent="mediaTouchEnd" @click="hide" @load="onImageLoaded" > diff --git a/src/modules/media_viewer.js b/src/modules/media_viewer.js index 38723763..d62aa7c1 100644 --- a/src/modules/media_viewer.js +++ b/src/modules/media_viewer.js @@ -62,16 +62,12 @@ const mediaViewer = { applyScaling (state, { scaling }) { state.scaling = state.origScaling * scaling }, - finishOffsets (state) { + finish (state) { state.origOffsets = [...state.offsets] - }, - finishScaling (state) { state.origScaling = state.scaling }, - revertOffsets (state) { + revert (state) { state.offsets = [...state.origOffsets] - }, - revertScaling (state) { state.scaling = state.origScaling } }, @@ -85,12 +81,10 @@ const mediaViewer = { commit('applyScaling', { scaling }) }, finish ({ commit }) { - commit('finishOffsets') - commit('finishScaling') + commit('finish') }, revert ({ commit }) { - commit('revertOffsets') - commit('revertScaling') + commit('revert') } } } diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index 8f406762..82337bc6 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -4,14 +4,21 @@ const DIRECTION_RIGHT = [1, 0] const DIRECTION_UP = [0, -1] const DIRECTION_DOWN = [0, 1] +const DISTANCE_MIN = 1 + const isSwipeEvent = e => (e.touches.length === 1) const isSwipeEventEnd = e => (e.changedTouches.length === 1) const isScaleEvent = e => (e.targetTouches.length === 2) -// const isScaleEventEnd = e => (e.changedTouches.length === 2) +const isScaleEventEnd = e => (e.targetTouches.length === 1) const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] +const vectorMinus = (a, b) => a.map((k, n) => k - b[n]) +const vectorAdd = (a, b) => a.map((k, n) => k + b[n]) + +const avgCoord = (coords) => [...coords].reduce(vectorAdd, [0, 0]).map(d => d / coords.length) + const touchCoord = touch => [touch.screenX, touch.screenY] const touchEventCoord = e => touchCoord(e.touches[0]) @@ -22,6 +29,8 @@ const perpendicular = v => [v[1], -v[0]] const dotProduct = (v1, v2) => v1[0] * v2[0] + v1[1] * v2[1] +// const numProduct = (num, v) => v.map(k => num * k) + const project = (v1, v2) => { const scalar = (dotProduct(v1, v2) / dotProduct(v2, v2)) return [scalar * v2[0], scalar * v2[1]] @@ -86,7 +95,7 @@ class SwipeAndScaleGesture { swipeEndCallback, pinchEndCallback, threshold = 30, perpendicularTolerance = 1.0 }) { - const nop = () => {} + const nop = () => { console.log('Warning: Not implemented') } this.direction = direction this.swipePreviewCallback = swipePreviewCallback || nop this.pinchPreviewCallback = pinchPreviewCallback || nop @@ -95,6 +104,7 @@ class SwipeAndScaleGesture { this.threshold = threshold this.perpendicularTolerance = perpendicularTolerance this._startPos = [0, 0] + this._startDistance = DISTANCE_MIN this._swiping = false } @@ -105,23 +115,51 @@ class SwipeAndScaleGesture { console.log('start pos:', this._startPos) this._swiping = true } else if (isScaleEvent(event)) { + const coords = [...event.targetTouches].map(touchCoord) + this._startPos = avgCoord(coords) + this._startDistance = vectorLength(deltaCoord(coords[0], coords[1])) + if (this._startDistance < DISTANCE_MIN) { + this._startDistance = DISTANCE_MIN + } this._scalePoints = [...event.targetTouches] this._swiping = false + console.log( + 'is scale event, start =', this._startPos, + 'dist =', this._startDistance) } } move (event) { + // console.log('move called', event) if (isSwipeEvent(event)) { const touch = event.changedTouches[0] const delta = deltaCoord(this._startPos, touchCoord(touch)) this.swipePreviewCallback(delta) } else if (isScaleEvent(event)) { + console.log('is scale event') + const coords = [...event.targetTouches].map(touchCoord) + const curPos = avgCoord(coords) + const curDistance = vectorLength(deltaCoord(coords[0], coords[1])) + const scaling = curDistance / this._startDistance + const posDiff = vectorMinus(curPos, this._startPos) + // const delta = vectorAdd(numProduct((1 - scaling), this._startPos), posDiff) + const delta = posDiff + // console.log( + // 'is scale event, cur =', curPos, + // 'dist =', curDistance, + // 'scale =', scaling, + // 'delta =', delta) + this.pinchPreviewCallback(delta, scaling) } } end (event) { console.log('end() called', event) + if (isScaleEventEnd(event)) { + this.pinchEndCallback() + } + if (!isSwipeEventEnd(event)) { console.log('not swipe event') return -- cgit v1.2.3-70-g09d2 From a36673a6a8cace69979605f72bcc4d7a9d439814 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 2 Aug 2021 17:42:10 -0400 Subject: Use pinch-zoom-element for pinch zoom functionality --- package.json | 1 + src/components/media_modal/media_modal.js | 5 ++- src/components/media_modal/media_modal.vue | 72 ++++++++++++++++++++++++------ src/components/pinch_zoom/pinch_zoom.js | 6 +++ src/components/pinch_zoom/pinch_zoom.vue | 11 +++++ src/main.js | 2 + src/modules/media_viewer.js | 2 +- yarn.lock | 11 +++++ 8 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 src/components/pinch_zoom/pinch_zoom.js create mode 100644 src/components/pinch_zoom/pinch_zoom.vue (limited to 'src/components/media_modal/media_modal.vue') diff --git a/package.json b/package.json index 5dd0e067..34029765 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@fortawesome/free-regular-svg-icons": "5.15.1", "@fortawesome/free-solid-svg-icons": "5.15.1", "@fortawesome/vue-fontawesome": "2.0.0", + "@kazvmoe-infra/pinch-zoom-element": "https://lily.kazv.moe/infra/pinch-zoom-element.git", "body-scroll-lock": "2.6.4", "chromatism": "3.0.0", "cropperjs": "1.4.3", diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 222e3478..684fbe45 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -1,6 +1,7 @@ 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 fileTypeService from '../../services/file_type/file_type.service.js' import GestureService from '../../services/gesture_service/gesture_service' import Flash from 'src/components/flash/flash.vue' @@ -26,12 +27,14 @@ const MediaModal = { components: { StillImage, VideoAttachment, + PinchZoom, Modal, Flash }, data () { return { - loading: false + loading: false, + pinchZoomOptions: {} } }, computed: { diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 853dec1d..a3fad4c5 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -4,20 +4,29 @@ class="media-modal-view" @backdropClicked="hide" > - + + + + + + + diff --git a/src/main.js b/src/main.js index 3895da89..03493525 100644 --- a/src/main.js +++ b/src/main.js @@ -45,6 +45,8 @@ Vue.use(VueClickOutside) Vue.use(PortalVue) Vue.use(VBodyScrollLock) +Vue.config.ignoredElements = ['pinch-zoom'] + Vue.component('FAIcon', FontAwesomeIcon) Vue.component('FALayers', FontAwesomeLayers) diff --git a/src/modules/media_viewer.js b/src/modules/media_viewer.js index d62aa7c1..ddcccb79 100644 --- a/src/modules/media_viewer.js +++ b/src/modules/media_viewer.js @@ -28,7 +28,7 @@ const mediaViewer = { commit('setMedia', media) dispatch('swipeScaler/reset') }, - setCurrentMedia ({ commit, state }, current) { + setCurrentMedia ({ commit, state, dispatch }, current) { const index = state.media.indexOf(current) commit('setCurrentMedia', index || 0) dispatch('swipeScaler/reset') diff --git a/yarn.lock b/yarn.lock index 2d873c25..176b0c7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -916,6 +916,12 @@ resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.0.tgz#63da3e459147cebb0a8d58eed81d6071db9f5973" integrity sha512-N3VKw7KzRfOm8hShUVldpinlm13HpvLBQgT63QS+aCrIRLwjoEUXY5Rcmttbfb6HkzZaeqjLqd/aZCQ53UjQpg== +"@kazvmoe-infra/pinch-zoom-element@https://lily.kazv.moe/infra/pinch-zoom-element.git": + version "1.1.1" + resolved "https://lily.kazv.moe/infra/pinch-zoom-element.git#de150c01057f0de0c3ef669917399fe370e36f40" + dependencies: + pointer-tracker "^2.0.3" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -6995,6 +7001,11 @@ pngjs@^5.0.0: resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== +pointer-tracker@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/pointer-tracker/-/pointer-tracker-2.4.0.tgz#78721c2d2201486db11ec1094377f03023b621b3" + integrity sha512-pWI2tpaM/XNtc9mUTv42Rmjf6mkHvE8LT5DDEq0G7baPNhxNM9E3CepubPplSoSLk9E5bwQrAMyDcPVmJyTW4g== + portal-vue@2.1.7: version "2.1.7" resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.7.tgz#ea08069b25b640ca08a5b86f67c612f15f4e4ad4" -- cgit v1.2.3-70-g09d2 From 29cd8fbd3bd9f936d2639a2edd773e1245b0b5a5 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 2 Aug 2021 19:11:59 -0400 Subject: Add swipe-click handler to media modal Now swiping will correctly change the current media, and with a good preview. Clicking without swiping closes the overlay. --- src/components/media_modal/media_modal.js | 58 ++++------- src/components/media_modal/media_modal.vue | 13 ++- src/components/pinch_zoom/pinch_zoom.js | 5 + src/modules/media_viewer.js | 56 +--------- src/services/gesture_service/gesture_service.js | 130 +++++++++++------------- 5 files changed, 94 insertions(+), 168 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 684fbe45..b4c0cfb4 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -2,10 +2,11 @@ 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 fileTypeService from '../../services/file_type/file_type.service.js' +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 Vuex from 'vuex' +import fileTypeService from '../../services/file_type/file_type.service.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronLeft, @@ -28,13 +29,15 @@ const MediaModal = { StillImage, VideoAttachment, PinchZoom, + SwipeClick, Modal, Flash }, data () { return { loading: false, - pinchZoomOptions: {} + swipeDirection: GestureService.DIRECTION_LEFT, + swipeThreshold: 50 } }, computed: { @@ -70,30 +73,19 @@ const MediaModal = { } }, created () { - this.mediaGesture = new GestureService.SwipeAndScaleGesture({ - direction: GestureService.DIRECTION_LEFT, - callbackPositive: this.goNext, - callbackNegative: this.goPrev, - swipePreviewCallback: this.handleSwipePreview, - swipeEndCallback: this.handleSwipeEnd, - pinchPreviewCallback: this.handlePinchPreview, - pinchEndCallback: this.handlePinchEnd, - threshold: 50 - }) + // this.mediaGesture = new GestureService.SwipeAndScaleGesture({ + // callbackPositive: this.goNext, + // callbackNegative: this.goPrev, + // swipePreviewCallback: this.handleSwipePreview, + // swipeEndCallback: this.handleSwipeEnd, + // pinchPreviewCallback: this.handlePinchPreview, + // pinchEndCallback: this.handlePinchEnd + // }) }, methods: { getType (media) { return fileTypeService.fileType(media.mimetype) }, - mediaTouchStart (e) { - this.mediaGesture.start(e) - }, - mediaTouchMove (e) { - this.mediaGesture.move(e) - }, - mediaTouchEnd (e) { - this.mediaGesture.end(e) - }, hide () { this.$store.dispatch('closeMediaViewer') }, @@ -105,6 +97,7 @@ const MediaModal = { this.loading = true } this.$store.dispatch('setCurrentMedia', newMedia) + this.$refs.pinchZoom.setTransform({ scale: 1, x: 0, y: 0 }) } }, goNext () { @@ -115,40 +108,25 @@ const MediaModal = { this.loading = true } this.$store.dispatch('setCurrentMedia', newMedia) + this.$refs.pinchZoom.setTransform({ scale: 1, x: 0, y: 0 }) } }, onImageLoaded () { this.loading = false }, handleSwipePreview (offsets) { - this.$store.dispatch('swipeScaler/apply', { - offsets: this.scaling > SCALING_ENABLE_MOVE_THRESHOLD ? offsets : onlyXAxis(offsets) - }) + this.$refs.pinchZoom.setTransform({ scale: 1, x: offsets[0], y: 0 }) }, handleSwipeEnd (sign) { - if (this.scaling > SCALING_ENABLE_MOVE_THRESHOLD) { - this.$store.dispatch('swipeScaler/finish') - return - } + console.log('handleSwipeEnd:', sign) if (sign === 0) { - this.$store.dispatch('swipeScaler/reset') + this.$refs.pinchZoom.setTransform({ scale: 1, x: 0, y: 0 }) } else if (sign > 0) { this.goNext() } else { this.goPrev() } }, - handlePinchPreview (offsets, scaling) { - console.log('handle pinch preview:', offsets, scaling) - this.$store.dispatch('swipeScaler/apply', { offsets, scaling }) - }, - handlePinchEnd () { - if (this.scaling > SCALING_RESET_MIN) { - this.$store.dispatch('swipeScaler/finish') - } else { - this.$store.dispatch('swipeScaler/reset') - } - }, handleKeyupEvent (e) { if (this.showing && e.keyCode === 27) { // escape this.hide() diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index a3fad4c5..e385024e 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -4,9 +4,16 @@ class="media-modal-view" @backdropClicked="hide" > - + k + offsets[n]) - }, - applyScaling (state, { scaling }) { - state.scaling = state.origScaling * scaling - }, - finish (state) { - state.origOffsets = [...state.offsets] - state.origScaling = state.scaling - }, - revert (state) { - state.offsets = [...state.origOffsets] - state.scaling = state.origScaling - } - }, - - actions: { - reset ({ commit }) { - commit('reset') - }, - apply ({ commit }, { offsets, scaling = 1 }) { - commit('applyOffsets', { offsets }) - commit('applyScaling', { scaling }) - }, - finish ({ commit }) { - commit('finish') - }, - revert ({ commit }) { - commit('revert') - } - } } } } diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index 82337bc6..f10dec3a 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -4,25 +4,27 @@ const DIRECTION_RIGHT = [1, 0] const DIRECTION_UP = [0, -1] const DIRECTION_DOWN = [0, 1] -const DISTANCE_MIN = 1 +// const DISTANCE_MIN = 1 -const isSwipeEvent = e => (e.touches.length === 1) -const isSwipeEventEnd = e => (e.changedTouches.length === 1) +// const isSwipeEvent = e => (e.touches.length === 1) +// const isSwipeEventEnd = e => (e.changedTouches.length === 1) -const isScaleEvent = e => (e.targetTouches.length === 2) -const isScaleEventEnd = e => (e.targetTouches.length === 1) +// const isScaleEvent = e => (e.targetTouches.length === 2) +// const isScaleEventEnd = e => (e.targetTouches.length === 1) const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] -const vectorMinus = (a, b) => a.map((k, n) => k - b[n]) -const vectorAdd = (a, b) => a.map((k, n) => k + b[n]) +// const vectorMinus = (a, b) => a.map((k, n) => k - b[n]) +// const vectorAdd = (a, b) => a.map((k, n) => k + b[n]) -const avgCoord = (coords) => [...coords].reduce(vectorAdd, [0, 0]).map(d => d / coords.length) +// const avgCoord = (coords) => [...coords].reduce(vectorAdd, [0, 0]).map(d => d / coords.length) const touchCoord = touch => [touch.screenX, touch.screenY] const touchEventCoord = e => touchCoord(e.touches[0]) +const pointerEventCoord = e => [e.clientX, e.clientY] + const vectorLength = v => Math.sqrt(v[0] * v[0] + v[1] * v[1]) const perpendicular = v => [v[1], -v[0]] @@ -78,104 +80,87 @@ const updateSwipe = (event, gesture) => { gesture._swiping = false } -class SwipeAndScaleGesture { +class SwipeAndClickGesture { // swipePreviewCallback(offsets: Array[Number]) // offsets: the offset vector which the underlying component should move, from the starting position - // pinchPreviewCallback(offsets: Array[Number], scaling: Number) - // offsets: the offset vector which the underlying component should move, from the starting position - // scaling: the scaling factor we should apply to the underlying component, from the starting position - // swipeEndcallback(sign: 0|-1|1) + // swipeEndCallback(sign: 0|-1|1) // sign: if the swipe does not meet the threshold, 0 // if the swipe meets the threshold in the positive direction, 1 // if the swipe meets the threshold in the negative direction, -1 constructor ({ direction, - // swipeStartCallback, pinchStartCallback, - swipePreviewCallback, pinchPreviewCallback, - swipeEndCallback, pinchEndCallback, + // swipeStartCallback + swipePreviewCallback, + swipeEndCallback, + swipeCancelCallback, + swipelessClickCallback, threshold = 30, perpendicularTolerance = 1.0 }) { const nop = () => { console.log('Warning: Not implemented') } this.direction = direction this.swipePreviewCallback = swipePreviewCallback || nop - this.pinchPreviewCallback = pinchPreviewCallback || nop this.swipeEndCallback = swipeEndCallback || nop - this.pinchEndCallback = pinchEndCallback || nop + this.swipeCancelCallback = swipeCancelCallback || nop + this.swipelessClickCallback = swipelessClickCallback || nop this.threshold = threshold this.perpendicularTolerance = perpendicularTolerance + this._reset() + } + + _reset () { this._startPos = [0, 0] - this._startDistance = DISTANCE_MIN + this._pointerId = -1 this._swiping = false + this._swiped = false } start (event) { console.log('start() called', event) - if (isSwipeEvent(event)) { - this._startPos = touchEventCoord(event) - console.log('start pos:', this._startPos) - this._swiping = true - } else if (isScaleEvent(event)) { - const coords = [...event.targetTouches].map(touchCoord) - this._startPos = avgCoord(coords) - this._startDistance = vectorLength(deltaCoord(coords[0], coords[1])) - if (this._startDistance < DISTANCE_MIN) { - this._startDistance = DISTANCE_MIN - } - this._scalePoints = [...event.targetTouches] - this._swiping = false - console.log( - 'is scale event, start =', this._startPos, - 'dist =', this._startDistance) - } + + this._startPos = pointerEventCoord(event) + this._pointerId = event.pointerId + console.log('start pos:', this._startPos) + this._swiping = true + this._swiped = false } move (event) { - // console.log('move called', event) - if (isSwipeEvent(event)) { - const touch = event.changedTouches[0] - const delta = deltaCoord(this._startPos, touchCoord(touch)) + if (this._swiping && this._pointerId === event.pointerId) { + this._swiped = true + + const coord = pointerEventCoord(event) + const delta = deltaCoord(this._startPos, coord) this.swipePreviewCallback(delta) - } else if (isScaleEvent(event)) { - console.log('is scale event') - const coords = [...event.targetTouches].map(touchCoord) - const curPos = avgCoord(coords) - const curDistance = vectorLength(deltaCoord(coords[0], coords[1])) - const scaling = curDistance / this._startDistance - const posDiff = vectorMinus(curPos, this._startPos) - // const delta = vectorAdd(numProduct((1 - scaling), this._startPos), posDiff) - const delta = posDiff - // console.log( - // 'is scale event, cur =', curPos, - // 'dist =', curDistance, - // 'scale =', scaling, - // 'delta =', delta) - this.pinchPreviewCallback(delta, scaling) } } - end (event) { - console.log('end() called', event) - if (isScaleEventEnd(event)) { - this.pinchEndCallback() - } - - if (!isSwipeEventEnd(event)) { - console.log('not swipe event') + cancel (event) { + if (!this._swiping || this._pointerId !== event.pointerId) { return } + + this.swipeCancelCallback() + } + + end (event) { if (!this._swiping) { console.log('not swiping') return } - this.swiping = false - console.log('is swipe event') + if (this._pointerId !== event.pointerId) { + console.log('pointer id does not match') + return + } + + this._swiping = false + + console.log('end: is swipe event') // movement too small - const touch = event.changedTouches[0] - const delta = deltaCoord(this._startPos, touchCoord(touch)) - this.swipePreviewCallback(delta) + const coord = pointerEventCoord(event) + const delta = deltaCoord(this._startPos, coord) const sign = (() => { if (vectorLength(delta) < this.threshold) { @@ -198,7 +183,12 @@ class SwipeAndScaleGesture { return isPositive ? 1 : -1 })() - this.swipeEndCallback(sign) + if (this._swiped) { + this.swipeEndCallback(sign) + } else { + this.swipelessClickCallback() + } + this._reset() } } @@ -210,7 +200,7 @@ const GestureService = { swipeGesture, beginSwipe, updateSwipe, - SwipeAndScaleGesture + SwipeAndClickGesture } export default GestureService -- cgit v1.2.3-70-g09d2 From 23a6b86ef3c976509bad4fb4f9a223a5724ec7e5 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 2 Aug 2021 19:21:18 -0400 Subject: Clean up --- src/components/media_modal/media_modal.js | 23 +++---------------- src/components/media_modal/media_modal.vue | 7 +++--- src/services/gesture_service/gesture_service.js | 30 ++++++++----------------- 3 files changed, 15 insertions(+), 45 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index b4c0cfb4..2f00f5f9 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -37,7 +37,9 @@ const MediaModal = { return { loading: false, swipeDirection: GestureService.DIRECTION_LEFT, - swipeThreshold: 50 + swipeThreshold: 50, + pinchZoomMinScale: 1, + pinchZoomScaleResetLimit: 1.2 } }, computed: { @@ -62,25 +64,6 @@ const MediaModal = { type () { return this.currentMedia ? this.getType(this.currentMedia) : null }, - scaling () { - return this.$store.state.mediaViewer.swipeScaler.scaling - }, - offsets () { - return this.$store.state.mediaViewer.swipeScaler.offsets - }, - transform () { - return `translate(${this.offsets[0]}px, ${this.offsets[1]}px) scale(${this.scaling}, ${this.scaling})` - } - }, - created () { - // this.mediaGesture = new GestureService.SwipeAndScaleGesture({ - // callbackPositive: this.goNext, - // callbackNegative: this.goPrev, - // swipePreviewCallback: this.handleSwipePreview, - // swipeEndCallback: this.handleSwipeEnd, - // pinchPreviewCallback: this.handlePinchPreview, - // pinchEndCallback: this.handlePinchEnd - // }) }, methods: { getType (media) { diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index e385024e..76cf4319 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -16,12 +16,11 @@ ref="pinchZoom" class="modal-image-container-inner" selector=".modal-image" - allow-pan-min-scale="1" - min-scale="1" - reset-to-min-scale-limit="1.2" reach-min-scale-strategy="reset" stop-propagate-handled="stop-propgate-handled" - :inner-class="'modal-image-container-inner'" + :allow-pan-min-scale="pinchZoomMinScale" + :min-scale="pinchZoomMinScale" + :reset-to-min-scale-limit="pinchZoomScaleResetLimit" > (e.touches.length === 1) -// const isSwipeEventEnd = e => (e.changedTouches.length === 1) - -// const isScaleEvent = e => (e.targetTouches.length === 2) -// const isScaleEventEnd = e => (e.targetTouches.length === 1) - const deltaCoord = (oldCoord, newCoord) => [newCoord[0] - oldCoord[0], newCoord[1] - oldCoord[1]] -// const vectorMinus = (a, b) => a.map((k, n) => k - b[n]) -// const vectorAdd = (a, b) => a.map((k, n) => k + b[n]) - -// const avgCoord = (coords) => [...coords].reduce(vectorAdd, [0, 0]).map(d => d / coords.length) - const touchCoord = touch => [touch.screenX, touch.screenY] const touchEventCoord = e => touchCoord(e.touches[0]) @@ -31,13 +18,14 @@ const perpendicular = v => [v[1], -v[0]] const dotProduct = (v1, v2) => v1[0] * v2[0] + v1[1] * v2[1] -// const numProduct = (num, v) => v.map(k => num * k) - const project = (v1, v2) => { const scalar = (dotProduct(v1, v2) / dotProduct(v2, v2)) return [scalar * v2[0], scalar * v2[1]] } +// const debug = console.log +const debug = () => {} + // direction: either use the constants above or an arbitrary 2d vector. // threshold: how many Px to move from touch origin before checking if the // callback should be called. @@ -96,7 +84,7 @@ class SwipeAndClickGesture { swipelessClickCallback, threshold = 30, perpendicularTolerance = 1.0 }) { - const nop = () => { console.log('Warning: Not implemented') } + const nop = () => { debug('Warning: Not implemented') } this.direction = direction this.swipePreviewCallback = swipePreviewCallback || nop this.swipeEndCallback = swipeEndCallback || nop @@ -115,11 +103,11 @@ class SwipeAndClickGesture { } start (event) { - console.log('start() called', event) + debug('start() called', event) this._startPos = pointerEventCoord(event) this._pointerId = event.pointerId - console.log('start pos:', this._startPos) + debug('start pos:', this._startPos) this._swiping = true this._swiped = false } @@ -145,18 +133,18 @@ class SwipeAndClickGesture { end (event) { if (!this._swiping) { - console.log('not swiping') + debug('not swiping') return } if (this._pointerId !== event.pointerId) { - console.log('pointer id does not match') + debug('pointer id does not match') return } this._swiping = false - console.log('end: is swipe event') + debug('end: is swipe event') // movement too small const coord = pointerEventCoord(event) -- cgit v1.2.3-70-g09d2 From ddf6c9cef085757ca008c9c7e67f998315948f45 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 2 Aug 2021 20:46:10 -0400 Subject: Allow pinch-zoom to fill the whole screen --- src/components/media_modal/media_modal.vue | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 76cf4319..80ce1dea 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -140,7 +140,10 @@ flex-direction: column; max-width: 90%; max-height: 95%; + width: 100%; + height: 100%; flex-grow: 1; + justify-content: center; &-inner { width: 100%; @@ -149,6 +152,7 @@ display: flex; flex-direction: column; align-items: center; + justify-content: center; } } -- cgit v1.2.3-70-g09d2 From 76727cd39cf588ffc1c15c0a2fd8f1ae30ada7ea Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 8 Sep 2021 21:28:29 -0400 Subject: Remove image box-shadow in media modal The box-shadow causes an image to be very blurry on Webkit browsers (experienced: Konqueror, Safari; heard of: Chrome) when scaled up if the initial size of the image is much smaller than the actual size (e.g. when viewing a very long picture). The shadow is not really obvious anyway. --- src/components/media_modal/media_modal.vue | 1 - 1 file changed, 1 deletion(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 80ce1dea..0fbdb558 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -161,7 +161,6 @@ max-height: 100%; min-width: 0; min-height: 0; - box-shadow: 0px 5px 15px 0 rgba(0, 0, 0, 0.5); image-orientation: from-image; // NOTE: only FF supports this animation: 0.1s cubic-bezier(0.7, 0, 1, 0.6) media-fadein; } -- cgit v1.2.3-70-g09d2 From 1128cc463c4b16c41ab21c554646a8104ba58826 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 8 Sep 2021 21:50:28 -0400 Subject: Fix video in media modal not displaying properly --- src/components/media_modal/media_modal.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 0fbdb558..abc1d797 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -5,6 +5,7 @@ @backdropClicked="hide" > Date: Sun, 20 Feb 2022 22:02:31 -0500 Subject: Fix webkit image blurs --- src/components/media_modal/media_modal.vue | 53 +++++++++++------------------- 1 file changed, 19 insertions(+), 34 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index abc1d797..ff9c4953 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -133,42 +133,28 @@ } } -.modal-image-container { - display: flex; - overflow: hidden; - align-items: center; - flex-direction: column; - max-width: 90%; - max-height: 95%; - width: 100%; - height: 100%; - flex-grow: 1; - justify-content: center; - - &-inner { + .modal-image-container { + display: flex; + overflow: hidden; + align-items: center; + flex-direction: column; + max-width: 90%; + max-height: 95%; width: 100%; height: 100%; flex-grow: 1; - display: flex; - flex-direction: column; - align-items: center; justify-content: center; - } -} - -.modal-image { - max-width: 100%; - max-height: 100%; - min-width: 0; - min-height: 0; - image-orientation: from-image; // NOTE: only FF supports this - animation: 0.1s cubic-bezier(0.7, 0, 1, 0.6) media-fadein; -} -//.modal-image { -// height: 90vh; -// width: 100%; -//} + &-inner { + width: 100%; + height: 100%; + flex-grow: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + } .description, .counter { @@ -189,9 +175,8 @@ } .modal-image { - max-width: 90%; - max-height: 90%; - box-shadow: 0px 5px 15px 0 rgba(0, 0, 0, 0.5); + max-width: 100%; + max-height: 100%; image-orientation: from-image; // NOTE: only FF supports this animation: 0.1s cubic-bezier(0.7, 0, 1, 0.6) media-fadein; -- cgit v1.2.3-70-g09d2 From 7dd1a0dd30773fd51508feaf93be53bdb744ec79 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 20 Feb 2022 22:45:58 -0500 Subject: Prevent hiding media viewer if swiped over SwipeClick --- src/components/media_modal/media_modal.js | 9 +++++++++ src/components/media_modal/media_modal.vue | 3 ++- src/services/gesture_service/gesture_service.js | 8 +++++--- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 4ed0b66f..0c19ed50 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -76,6 +76,15 @@ const MediaModal = { 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) diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index ff9c4953..1aa66a55 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -2,10 +2,11 @@ {} this.direction = direction @@ -90,6 +92,7 @@ class SwipeAndClickGesture { this.swipeCancelCallback = swipeCancelCallback || nop this.swipelessClickCallback = swipelessClickCallback || nop this.threshold = typeof threshold === 'function' ? threshold : () => threshold + this.disableClickThreshold = typeof disableClickThreshold === 'function' ? disableClickThreshold : () => disableClickThreshold this.perpendicularTolerance = perpendicularTolerance this._reset() } @@ -169,7 +172,6 @@ class SwipeAndClickGesture { return isPositive ? 1 : -1 })() - const swiped = this._swiped if (this._swiped) { this.swipeEndCallback(sign) } @@ -178,7 +180,7 @@ class SwipeAndClickGesture { // the end point is far from the starting point // so for other kinds of pointers do not check // whether we have swiped - if (swiped && event.pointerType === 'mouse') { + if (vectorLength(delta) >= this.disableClickThreshold() && event.pointerType === 'mouse') { this._preventNextClick = true } } -- cgit v1.2.3-70-g09d2 From 5fb302d0f1f311985f7d26a8e8f11e15ec72d26f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 3 Mar 2022 12:51:13 -0500 Subject: Add hide button to media modal --- src/components/media_modal/media_modal.js | 6 ++- src/components/media_modal/media_modal.vue | 74 ++++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 20 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index e7efc018..01a90377 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -10,13 +10,15 @@ import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronLeft, faChevronRight, - faCircleNotch + faCircleNotch, + faTimes } from '@fortawesome/free-solid-svg-icons' library.add( faChevronLeft, faChevronRight, - faCircleNotch + faCircleNotch, + faTimes ) const MediaModal = { diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 1aa66a55..2d00d7fb 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -58,25 +58,36 @@ + + -- cgit v1.2.3-70-g09d2 From 1b204012eaf3fcc262689a070424c618d8d3a917 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 6 Mar 2022 18:38:57 -0500 Subject: Make media modal buttons larger --- src/components/media_modal/media_modal.vue | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src/components/media_modal/media_modal.vue') diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 2d00d7fb..708a43c6 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -115,9 +115,10 @@