Rewrite Modals/ImageViewer with composition API
This commit is contained in:
parent
2acc8468ca
commit
892719141b
|
@ -11,7 +11,7 @@
|
|||
<span class="button-area"
|
||||
><el-button type="text" v-show="showLeft" @click="decrementIndex()"> <font-awesome-icon icon="angle-left" /> </el-button
|
||||
></span>
|
||||
<Media :src="imageURL" :type="imageType"></Media>
|
||||
<Media :src="imageURL" :imageType="imageType"></Media>
|
||||
<span class="button-area"
|
||||
><el-button type="text" v-show="showRight" @click="incrementIndex()"> <font-awesome-icon icon="angle-right" /> </el-button
|
||||
></span>
|
||||
|
@ -21,51 +21,49 @@
|
|||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Media from './Media'
|
||||
import { mapState } from 'vuex'
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useStore } from '@/store'
|
||||
import { ACTION_TYPES } from '@/store/TimelineSpace/Modals/ImageViewer'
|
||||
import Media from './ImageViewer/Media.vue'
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'image-viewer',
|
||||
components: {
|
||||
Media
|
||||
},
|
||||
name: 'image-viewer',
|
||||
computed: {
|
||||
...mapState({
|
||||
modalOpen: state => state.TimelineSpace.Modals.ImageViewer.modalOpen
|
||||
}),
|
||||
imageURL() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageURL']
|
||||
},
|
||||
imageType() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageType']
|
||||
},
|
||||
showLeft() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showLeft']
|
||||
},
|
||||
showRight() {
|
||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showRight']
|
||||
setup() {
|
||||
const space = 'TimelineSpace/Modals/ImageViewer'
|
||||
const store = useStore()
|
||||
|
||||
const modalOpen = computed(() => store.state.TimelineSpace.Modals.ImageViewer.modalOpen)
|
||||
const imageURL = computed(() => store.getters[`${space}/imageURL`])
|
||||
const imageType = computed(() => store.getters[`${space}/imageType`])
|
||||
const showLeft = computed(() => store.getters[`${space}/showLeft`])
|
||||
const showRight = computed(() => store.getters[`${space}/showRight`])
|
||||
|
||||
const close = () => {
|
||||
store.dispatch(`${space}/${ACTION_TYPES.CLOSE_MODAL}`)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/closeModal')
|
||||
},
|
||||
decrementIndex() {
|
||||
if (this.showLeft) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/decrementIndex')
|
||||
},
|
||||
incrementIndex() {
|
||||
if (this.showRight) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/incrementIndex')
|
||||
},
|
||||
closeHandle(event) {
|
||||
switch (event.srcKey) {
|
||||
case 'close':
|
||||
this.close()
|
||||
break
|
||||
}
|
||||
const decrementIndex = () => {
|
||||
if (showLeft.value) store.dispatch(`${space}/${ACTION_TYPES.DECREMENT_INDEX}`)
|
||||
}
|
||||
const incrementIndex = () => {
|
||||
if (showRight.value) store.dispatch(`${space}/${ACTION_TYPES.INCREMENT_INDEX}`)
|
||||
}
|
||||
|
||||
return {
|
||||
modalOpen,
|
||||
imageURL,
|
||||
imageType,
|
||||
showLeft,
|
||||
showRight,
|
||||
close,
|
||||
decrementIndex,
|
||||
incrementIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<div id="current-media" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.8)">
|
||||
<video :src="imageSrc" v-if="isMovie()" autoplay loop controls v-on:loadstart="loaded()"></video>
|
||||
<video :src="imageSrc" v-else-if="isGIF()" autoplay loop v-on:loadstart="loaded()"></video>
|
||||
<video :src="imageSrc" v-else-if="isAudio()" autoplay loop controls v-on:loadstart="loaded()"></video>
|
||||
<img :src="imageSrc" v-else v-on:load="loaded()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, toRefs, watch, computed } from 'vue'
|
||||
import { useStore } from '@/store'
|
||||
import { ACTION_TYPES } from '@/store/TimelineSpace/Modals/ImageViewer'
|
||||
import exifImageUrl from '@/components/utils/exifImageUrl'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Media',
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
imageType: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const srcRef = toRefs(props).src
|
||||
const imageTypeRef = toRefs(props).imageType
|
||||
const imageSrc = ref('')
|
||||
imageSrc.value = srcRef.value
|
||||
const store = useStore()
|
||||
const loading = computed(() => store.state.TimelineSpace.Modals.ImageViewer.loading)
|
||||
|
||||
const isMovie = () => ['video'].includes(imageTypeRef.value)
|
||||
const isGIF = () => ['gifv'].includes(imageTypeRef.value)
|
||||
const isAudio = () => ['audio'].includes(imageTypeRef.value)
|
||||
|
||||
watch(srcRef, async (newSrc, _oldSrc) => {
|
||||
imageSrc.value = newSrc
|
||||
if (newSrc && !isMovie() && !isGIF() && !isAudio()) {
|
||||
try {
|
||||
const transformed = await exifImageUrl(newSrc)
|
||||
imageSrc.value = transformed
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const loaded = () => store.dispatch(`TimelineSpace/Modals/ImageViewer/${ACTION_TYPES.LOADED}`)
|
||||
|
||||
return {
|
||||
imageSrc,
|
||||
loading,
|
||||
isMovie,
|
||||
isGIF,
|
||||
isAudio,
|
||||
loaded
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#current-media {
|
||||
max-width: 80%;
|
||||
min-width: 10%;
|
||||
height: 80%;
|
||||
display: inline-flex;
|
||||
|
||||
img,
|
||||
video {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,103 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
id="current-media"
|
||||
v-loading="loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
>
|
||||
<video
|
||||
:src="src"
|
||||
v-if="isMovieFile()"
|
||||
autoplay
|
||||
loop
|
||||
controls
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<video
|
||||
:src="src"
|
||||
v-else-if="isGIF()"
|
||||
autoplay
|
||||
loop
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<video
|
||||
:src="src"
|
||||
v-else-if="isAudio()"
|
||||
autoplay
|
||||
loop
|
||||
controls
|
||||
v-on:loadstart="loaded()"
|
||||
></video>
|
||||
<img :src="imageSrc" v-else v-on:load="loaded()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import exifImageUrl from '@/components/utils/exifImageUrl'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imageSrc: this.src,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
src: async function (newSrc, _oldSrc) {
|
||||
this.imageSrc = newSrc
|
||||
if (newSrc && !this.isMovieFile() && !this.isGIF()) {
|
||||
try {
|
||||
const transformed = await exifImageUrl(newSrc)
|
||||
this.imageSrc = transformed
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
loading: (state) => state.TimelineSpace.Modals.ImageViewer.loading,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
isMovieFile() {
|
||||
return ['video'].includes(this.type)
|
||||
},
|
||||
isGIF() {
|
||||
return ['gifv'].includes(this.type)
|
||||
},
|
||||
isAudio() {
|
||||
return ['audio'].includes(this.type)
|
||||
},
|
||||
async loaded() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/loaded')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#current-media {
|
||||
max-width: 80%;
|
||||
min-width: 10%;
|
||||
height: 80%;
|
||||
display: inline-flex;
|
||||
|
||||
img,
|
||||
video {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="shortcut">
|
||||
<el-dialog :title="$t('modals.shortcut.title')" v-model="shortcutModal" width="500px" class="shortcut-modal">
|
||||
<el-dialog :title="$t('modals.shortcut.title')" v-model="shortcutModal" width="500px" custom-class="shortcut-modal">
|
||||
<table class="shortcuts">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
|
|
@ -46,28 +46,36 @@ const mutations: MutationTree<ImageViewerState> = {
|
|||
}
|
||||
}
|
||||
|
||||
export const ACTION_TYPES = {
|
||||
OPEN_MODAL: 'openModal',
|
||||
CLOSE_MODAL: 'closeModal',
|
||||
INCREMENT_INDEX: 'incrementIndex',
|
||||
DECREMENT_INDEX: 'decrementIndex',
|
||||
LOADED: 'loaded'
|
||||
}
|
||||
|
||||
const actions: ActionTree<ImageViewerState, RootState> = {
|
||||
openModal: ({ commit }, { currentIndex, mediaList }) => {
|
||||
[ACTION_TYPES.OPEN_MODAL]: ({ commit }, { currentIndex, mediaList }) => {
|
||||
commit(MUTATION_TYPES.CHANGE_MODAL, true)
|
||||
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, currentIndex as number)
|
||||
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, mediaList as Array<Entity.Attachment>)
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
},
|
||||
closeModal: ({ commit }) => {
|
||||
[ACTION_TYPES.CLOSE_MODAL]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.CHANGE_MODAL, false)
|
||||
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, -1)
|
||||
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, [])
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
},
|
||||
incrementIndex: ({ commit }) => {
|
||||
[ACTION_TYPES.INCREMENT_INDEX]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.INCREMENT_INDEX)
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
},
|
||||
decrementIndex: ({ commit }) => {
|
||||
[ACTION_TYPES.DECREMENT_INDEX]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.DECREMENT_INDEX)
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
},
|
||||
loaded: ({ commit }) => {
|
||||
[ACTION_TYPES.LOADED]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue