feat: Add video preview & player in conversation (#3201)
This commit is contained in:
parent
98e9fedfa6
commit
74db319a7c
4 changed files with 85 additions and 16 deletions
|
@ -17,7 +17,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image,
|
||||||
|
.video {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -29,17 +30,32 @@
|
||||||
max-width: 85%;
|
max-width: 85%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-video {
|
||||||
|
max-height: 75vh;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
background-image: linear-gradient(-180deg, transparent 3%, $color-heading 130%);
|
background-image: linear-gradient(-180deg, transparent 3%, $color-heading 130%);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
content: '';
|
content: '';
|
||||||
height: 20%;
|
height: 20%;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: .8;
|
opacity: 0.8;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.video {
|
||||||
|
.modal-container {
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
.modal--close {
|
||||||
|
z-index: var(--z-index-low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversations-list-wrap {
|
.conversations-list-wrap {
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
<audio v-else-if="attachment.file_type === 'audio'" controls>
|
<audio v-else-if="attachment.file_type === 'audio'" controls>
|
||||||
<source :src="attachment.data_url" />
|
<source :src="attachment.data_url" />
|
||||||
</audio>
|
</audio>
|
||||||
|
<bubble-video
|
||||||
|
v-else-if="attachment.file_type === 'video'"
|
||||||
|
:url="attachment.data_url"
|
||||||
|
:readable-time="readableTime"
|
||||||
|
/>
|
||||||
<bubble-file
|
<bubble-file
|
||||||
v-else
|
v-else
|
||||||
:url="attachment.data_url"
|
:url="attachment.data_url"
|
||||||
|
@ -91,6 +96,7 @@ import BubbleMailHead from './bubble/MailHead';
|
||||||
import BubbleText from './bubble/Text';
|
import BubbleText from './bubble/Text';
|
||||||
import BubbleImage from './bubble/Image';
|
import BubbleImage from './bubble/Image';
|
||||||
import BubbleFile from './bubble/File';
|
import BubbleFile from './bubble/File';
|
||||||
|
import BubbleVideo from './bubble/Video.vue';
|
||||||
import BubbleActions from './bubble/Actions';
|
import BubbleActions from './bubble/Actions';
|
||||||
|
|
||||||
import Spinner from 'shared/components/Spinner';
|
import Spinner from 'shared/components/Spinner';
|
||||||
|
@ -108,6 +114,7 @@ export default {
|
||||||
BubbleText,
|
BubbleText,
|
||||||
BubbleImage,
|
BubbleImage,
|
||||||
BubbleFile,
|
BubbleFile,
|
||||||
|
BubbleVideo,
|
||||||
BubbleMailHead,
|
BubbleMailHead,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
Spinner,
|
Spinner,
|
||||||
|
@ -236,14 +243,6 @@ export default {
|
||||||
isMessageDeleted() {
|
isMessageDeleted() {
|
||||||
return this.contentAttributes.deleted;
|
return this.contentAttributes.deleted;
|
||||||
},
|
},
|
||||||
hasImageAttachment() {
|
|
||||||
if (this.hasAttachments && this.data.attachments.length > 0) {
|
|
||||||
const { attachments = [{}] } = this.data;
|
|
||||||
const { file_type: fileType } = attachments[0];
|
|
||||||
return fileType === 'image';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
hasText() {
|
hasText() {
|
||||||
return !!this.data.content;
|
return !!this.data.content;
|
||||||
},
|
},
|
||||||
|
@ -270,7 +269,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
bubble: this.isBubble,
|
bubble: this.isBubble,
|
||||||
'is-private': this.data.private,
|
'is-private': this.data.private,
|
||||||
'is-image': this.hasImageAttachment,
|
'is-image': this.hasMediaAttachment('image'),
|
||||||
|
'is-video': this.hasMediaAttachment('video'),
|
||||||
'is-text': this.hasText,
|
'is-text': this.hasText,
|
||||||
'is-from-bot': this.isSentByBot,
|
'is-from-bot': this.isSentByBot,
|
||||||
};
|
};
|
||||||
|
@ -288,6 +288,14 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
hasMediaAttachment(type) {
|
||||||
|
if (this.hasAttachments && this.data.attachments.length > 0) {
|
||||||
|
const { attachments = [{}] } = this.data;
|
||||||
|
const { file_type: fileType } = attachments[0];
|
||||||
|
return fileType === type;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
handleContextMenuClick() {
|
handleContextMenuClick() {
|
||||||
this.showContextMenu = !this.showContextMenu;
|
this.showContextMenu = !this.showContextMenu;
|
||||||
},
|
},
|
||||||
|
@ -315,17 +323,28 @@ export default {
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.wrap {
|
.wrap {
|
||||||
> .bubble {
|
> .bubble {
|
||||||
&.is-image {
|
&.is-image,
|
||||||
|
&.is-video {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.image {
|
.image,
|
||||||
|
.video {
|
||||||
max-width: 32rem;
|
max-width: 32rem;
|
||||||
padding: var(--space-micro);
|
padding: var(--space-micro);
|
||||||
|
|
||||||
> img {
|
> img,
|
||||||
|
> video {
|
||||||
border-radius: var(--border-radius-medium);
|
border-radius: var(--border-radius-medium);
|
||||||
}
|
}
|
||||||
|
> video {
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.video {
|
||||||
|
height: 18rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-image {
|
.is-image,
|
||||||
|
.is-video {
|
||||||
.message-text--metadata {
|
.message-text--metadata {
|
||||||
.time {
|
.time {
|
||||||
bottom: var(--space-smaller);
|
bottom: var(--space-smaller);
|
||||||
|
@ -206,7 +207,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-image {
|
&.is-image,
|
||||||
|
&.is-video {
|
||||||
.time {
|
.time {
|
||||||
position: inherit;
|
position: inherit;
|
||||||
padding-left: var(--space-one);
|
padding-left: var(--space-one);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<template>
|
||||||
|
<div class="video message-text__wrap">
|
||||||
|
<video :src="url" muted playsInline @click="onClick" />
|
||||||
|
<woot-modal :show.sync="show" :on-close="onClose">
|
||||||
|
<video :src="url" controls playsInline class="modal-video" />
|
||||||
|
</woot-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClose() {
|
||||||
|
this.show = false;
|
||||||
|
},
|
||||||
|
onClick() {
|
||||||
|
this.show = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
Loading…
Reference in a new issue