feat: Add video preview & player in conversation (#3201)

This commit is contained in:
Sanju 2021-10-25 19:46:37 +05:30 committed by GitHub
parent 98e9fedfa6
commit 74db319a7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 16 deletions

View file

@ -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 {

View file

@ -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;
} }
} }

View file

@ -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);

View file

@ -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>