Skip to content
Merged
4 changes: 4 additions & 0 deletions src/components/SvgIcon/SvgIcon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
fill: var(--chat-icon-color-close-outline);
}

#vac-icon-close-outline-preview {
fill: var(--chat-icon-color-close-preview);
}

#vac-icon-send {
fill: var(--chat-icon-color-send);
}
Expand Down
1 change: 0 additions & 1 deletion src/lib/ChatWindow.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
background: var(--chat-content-bg-color);
color: var(--chat-color);
overflow-wrap: break-word;
position: relative;
white-space: normal;
border: var(--chat-container-border);
border-radius: var(--chat-container-border-radius);
Expand Down
25 changes: 21 additions & 4 deletions src/lib/ChatWindow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,20 @@
</template>
</room>
</div>
<transition name="vac-fade-preview" appear>
<media-preview
v-if="showMediaPreview"
:file="previewFile"
@close-media-preview="showMediaPreview = false"
/>
</transition>
</div>
</template>

<script>
import RoomsList from './RoomsList/RoomsList'
import Room from './Room/Room'
import MediaPreview from './MediaPreview/MediaPreview'

import locales from '../locales'
import { defaultThemeStyles, cssThemeVars } from '../themes'
Expand All @@ -96,7 +104,8 @@ export default {
name: 'ChatContainer',
components: {
RoomsList,
Room
Room,
MediaPreview
},

props: {
Expand Down Expand Up @@ -158,7 +167,8 @@ export default {
roomMessage: { type: String, default: '' },
scrollDistance: { type: Number, default: 60 },
acceptedFiles: { type: String, default: '*' },
templatesText: { type: Array, default: null }
templatesText: { type: Array, default: null },
mediaPreviewEnabled: { type: Boolean, default: true }
},

emits: [
Expand All @@ -185,7 +195,9 @@ export default {
room: {},
loadingMoreRooms: false,
showRoomsList: true,
isMobile: false
isMobile: false,
showMediaPreview: false,
previewFile: {}
}
},

Expand Down Expand Up @@ -327,7 +339,12 @@ export default {
this.$emit('delete-message', { message, roomId: this.room.roomId })
},
openFile({ message, file }) {
this.$emit('open-file', { message, file })
if (this.mediaPreviewEnabled && file.action === 'preview') {
this.previewFile = file.file
this.showMediaPreview = true
} else {
this.$emit('open-file', { message, file })
}
},
openUserTag({ user }) {
this.$emit('open-user-tag', { user })
Expand Down
38 changes: 38 additions & 0 deletions src/lib/MediaPreview/MediaPreview.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.vac-media-preview {
position: absolute;
top: 0;
left: 0;
z-index: 99;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
outline: none;

.vac-media-preview-container {
width: 100%;
height: 100%;
}

.vac-image-preview {
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}

.vac-svg-button {
position: absolute;
top: 30px;
right: 30px;
transform: scale(1.4);
}

@media only screen and (max-width: 768px) {
.vac-svg-button {
top: 20px;
right: 20px;
transform: scale(1.2);
}
}
}
69 changes: 69 additions & 0 deletions src/lib/MediaPreview/MediaPreview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<template>
<div
ref="modal"
tabindex="0"
class="vac-media-preview"
@click.stop="closeModal"
@keydown.esc="closeModal"
>
<transition name="vac-bounce-preview" appear>
<div v-if="isImage" class="vac-media-preview-container">
<div
class="vac-image-preview"
:style="{
'background-image': `url('${file.url}')`
}"
/>
</div>

<div v-else-if="isVideo" class="vac-media-preview-container">
<video width="100%" height="100%" controls autoplay>
<source :src="file.url" />
</video>
</div>
</transition>

<div class="vac-svg-button">
<slot name="preview-close-icon">
<svg-icon name="close-outline" param="preview" />
</slot>
</div>
</div>
</template>
<script>
import SvgIcon from '../../components/SvgIcon/SvgIcon'

const { isImageFile, isVideoFile } = require('../../utils/media-file')

export default {
name: 'MediaPreview',
components: {
SvgIcon
},

props: {
file: { type: Object, required: true }
},

emits: ['close-media-preview'],

computed: {
isImage() {
return isImageFile(this.file)
},
isVideo() {
return isVideoFile(this.file)
}
},

mounted() {
this.$refs.modal.focus()
},

methods: {
closeModal() {
this.$emit('close-media-preview')
}
}
}
</script>
1 change: 1 addition & 0 deletions src/lib/Message/MessageFiles/MessageFile/MessageFile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
width: 350px;
max-width: 100%;
margin: 4px auto 5px;
cursor: pointer;

video {
border-radius: 4px;
Expand Down
6 changes: 5 additions & 1 deletion src/lib/Message/MessageFiles/MessageFile/MessageFile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@
</div>
</div>

<div v-else-if="isVideo" class="vac-video-container">
<div
v-else-if="isVideo"
class="vac-video-container"
@click.stop.prevent="openFile('preview')"
>
<video width="100%" height="100%" controls>
<source :src="file.url" />
</video>
Expand Down
31 changes: 31 additions & 0 deletions src/styles/animation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,34 @@
transform: scale(1);
}
}

// Open media preview animation
.vac-fade-preview-enter {
opacity: 0;
}

.vac-fade-preview-enter-active {
transition: opacity 0.1s;
}

.vac-fade-preview-leave-active {
transition: opacity 0.2s;
opacity: 0;
}

.vac-bounce-preview-enter-active {
animation: vac-bounce-image-in 0.4s;
}

.vac-bounce-preview-leave-active {
animation: vac-bounce-image-in 0.3s reverse;
}

@keyframes vac-bounce-image-in {
0% {
transform: scale(0.6);
}
100% {
transform: scale(1);
}
}
2 changes: 2 additions & 0 deletions src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

@import '../lib/ChatWindow';

@import '../lib/MediaPreview/MediaPreview';

@import '../lib/Room/Room';
@import '../lib/Room/RoomEmojis/RoomEmojis';
@import '../lib/Room/RoomHeader/RoomHeader';
Expand Down
3 changes: 3 additions & 0 deletions src/themes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export const defaultThemeStyles = {
file: '#1976d2',
paperclip: '#1976d2',
closeOutline: '#000',
closePreview: '#fff',
send: '#1976d2',
sendDisabled: '#9ca6af',
emoji: '#1976d2',
Expand Down Expand Up @@ -259,6 +260,7 @@ export const defaultThemeStyles = {
file: '#1976d2',
paperclip: '#fff',
closeOutline: '#fff',
closePreview: '#fff',
send: '#fff',
sendDisabled: '#646a70',
emoji: '#fff',
Expand Down Expand Up @@ -407,6 +409,7 @@ export const cssThemeVars = ({
'--chat-icon-color-file': icons.file,
'--chat-icon-color-paperclip': icons.paperclip,
'--chat-icon-color-close-outline': icons.closeOutline,
'--chat-icon-color-close-preview': icons.closePreview,
'--chat-icon-color-send': icons.send,
'--chat-icon-color-send-disabled': icons.sendDisabled,
'--chat-icon-color-emoji': icons.emoji,
Expand Down