Rewrite Modals/ImageViewer with composition API
This commit is contained in:
parent
2acc8468ca
commit
892719141b
|
@ -11,7 +11,7 @@
|
||||||
<span class="button-area"
|
<span class="button-area"
|
||||||
><el-button type="text" v-show="showLeft" @click="decrementIndex()"> <font-awesome-icon icon="angle-left" /> </el-button
|
><el-button type="text" v-show="showLeft" @click="decrementIndex()"> <font-awesome-icon icon="angle-left" /> </el-button
|
||||||
></span>
|
></span>
|
||||||
<Media :src="imageURL" :type="imageType"></Media>
|
<Media :src="imageURL" :imageType="imageType"></Media>
|
||||||
<span class="button-area"
|
<span class="button-area"
|
||||||
><el-button type="text" v-show="showRight" @click="incrementIndex()"> <font-awesome-icon icon="angle-right" /> </el-button
|
><el-button type="text" v-show="showRight" @click="incrementIndex()"> <font-awesome-icon icon="angle-right" /> </el-button
|
||||||
></span>
|
></span>
|
||||||
|
@ -21,51 +21,49 @@
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Media from './Media'
|
import { defineComponent, computed } from 'vue'
|
||||||
import { mapState } from 'vuex'
|
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: {
|
components: {
|
||||||
Media
|
Media
|
||||||
},
|
},
|
||||||
name: 'image-viewer',
|
setup() {
|
||||||
computed: {
|
const space = 'TimelineSpace/Modals/ImageViewer'
|
||||||
...mapState({
|
const store = useStore()
|
||||||
modalOpen: state => state.TimelineSpace.Modals.ImageViewer.modalOpen
|
|
||||||
}),
|
const modalOpen = computed(() => store.state.TimelineSpace.Modals.ImageViewer.modalOpen)
|
||||||
imageURL() {
|
const imageURL = computed(() => store.getters[`${space}/imageURL`])
|
||||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageURL']
|
const imageType = computed(() => store.getters[`${space}/imageType`])
|
||||||
},
|
const showLeft = computed(() => store.getters[`${space}/showLeft`])
|
||||||
imageType() {
|
const showRight = computed(() => store.getters[`${space}/showRight`])
|
||||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/imageType']
|
|
||||||
},
|
const close = () => {
|
||||||
showLeft() {
|
store.dispatch(`${space}/${ACTION_TYPES.CLOSE_MODAL}`)
|
||||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showLeft']
|
|
||||||
},
|
|
||||||
showRight() {
|
|
||||||
return this.$store.getters['TimelineSpace/Modals/ImageViewer/showRight']
|
|
||||||
}
|
}
|
||||||
},
|
const decrementIndex = () => {
|
||||||
methods: {
|
if (showLeft.value) store.dispatch(`${space}/${ACTION_TYPES.DECREMENT_INDEX}`)
|
||||||
close() {
|
}
|
||||||
this.$store.dispatch('TimelineSpace/Modals/ImageViewer/closeModal')
|
const incrementIndex = () => {
|
||||||
},
|
if (showRight.value) store.dispatch(`${space}/${ACTION_TYPES.INCREMENT_INDEX}`)
|
||||||
decrementIndex() {
|
}
|
||||||
if (this.showLeft) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/decrementIndex')
|
|
||||||
},
|
return {
|
||||||
incrementIndex() {
|
modalOpen,
|
||||||
if (this.showRight) this.$store.dispatch('TimelineSpace/Modals/ImageViewer/incrementIndex')
|
imageURL,
|
||||||
},
|
imageType,
|
||||||
closeHandle(event) {
|
showLeft,
|
||||||
switch (event.srcKey) {
|
showRight,
|
||||||
case 'close':
|
close,
|
||||||
this.close()
|
decrementIndex,
|
||||||
break
|
incrementIndex
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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>
|
<template>
|
||||||
<div class="shortcut">
|
<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">
|
<table class="shortcuts">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<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> = {
|
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_MODAL, true)
|
||||||
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, currentIndex as number)
|
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, currentIndex as number)
|
||||||
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, mediaList as Array<Entity.Attachment>)
|
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, mediaList as Array<Entity.Attachment>)
|
||||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||||
},
|
},
|
||||||
closeModal: ({ commit }) => {
|
[ACTION_TYPES.CLOSE_MODAL]: ({ commit }) => {
|
||||||
commit(MUTATION_TYPES.CHANGE_MODAL, false)
|
commit(MUTATION_TYPES.CHANGE_MODAL, false)
|
||||||
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, -1)
|
commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, -1)
|
||||||
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, [])
|
commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, [])
|
||||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||||
},
|
},
|
||||||
incrementIndex: ({ commit }) => {
|
[ACTION_TYPES.INCREMENT_INDEX]: ({ commit }) => {
|
||||||
commit(MUTATION_TYPES.INCREMENT_INDEX)
|
commit(MUTATION_TYPES.INCREMENT_INDEX)
|
||||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||||
},
|
},
|
||||||
decrementIndex: ({ commit }) => {
|
[ACTION_TYPES.DECREMENT_INDEX]: ({ commit }) => {
|
||||||
commit(MUTATION_TYPES.DECREMENT_INDEX)
|
commit(MUTATION_TYPES.DECREMENT_INDEX)
|
||||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||||
},
|
},
|
||||||
loaded: ({ commit }) => {
|
[ACTION_TYPES.LOADED]: ({ commit }) => {
|
||||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue