parent
601e0d4a6c
commit
b2a6a5d145
5 changed files with 241 additions and 11 deletions
|
|
@ -185,10 +185,8 @@ $admin-fg: white;
|
|||
background-color: $admin-bg;
|
||||
}
|
||||
.audio-bubble {
|
||||
overflow: scroll;
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
max-width: 70%;
|
||||
width: 70%;
|
||||
height: 50px;
|
||||
}
|
||||
.bubble.image-bubble {
|
||||
padding: 0px;
|
||||
|
|
@ -252,10 +250,14 @@ $admin-fg: white;
|
|||
max-width: 70%;
|
||||
}
|
||||
.audio-bubble {
|
||||
overflow: scroll;
|
||||
background-color: #e5e5e5;
|
||||
border-radius: 10px 10px 0 10px;
|
||||
padding: 8px;
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
position: relative;
|
||||
max-width: 70%;
|
||||
width: 70%;
|
||||
height: 50px;
|
||||
}
|
||||
.video2-bubble {
|
||||
background-color: #e5e5e5;
|
||||
|
|
@ -384,6 +386,40 @@ $admin-fg: white;
|
|||
user-select: text;
|
||||
}
|
||||
|
||||
.audio-player {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
.currentColor {
|
||||
background-color: #000000 !important;
|
||||
}
|
||||
.v-icon {
|
||||
color: black !important;
|
||||
}
|
||||
.from-admin & {
|
||||
color: $admin-fg;
|
||||
.currentColor {
|
||||
background-color: #555555 !important;
|
||||
}
|
||||
.v-icon {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
.play-time {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 13 * $chat-text-size;
|
||||
}
|
||||
.play-progress {
|
||||
padding: 0px 10px;
|
||||
.v-slider__thumb {
|
||||
display: none;
|
||||
}
|
||||
&:hover .v-slider__thumb {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.message-operations-strut {
|
||||
position: relative;
|
||||
height: 0px;
|
||||
|
|
|
|||
185
src/components/messages/AudioPlayer.vue
Normal file
185
src/components/messages/AudioPlayer.vue
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
<template>
|
||||
<div class="audio-player d-flex flex-row" style="align-items: center">
|
||||
<audio ref="player" :src="src" @durationchange="updateDuration">
|
||||
<slot></slot>
|
||||
</audio>
|
||||
<v-btn v-if="playing" @click.stop="pause" icon
|
||||
><v-icon size="20">pause</v-icon></v-btn
|
||||
>
|
||||
<v-btn v-else @click.stop="play" icon
|
||||
><v-icon size="20">play_arrow</v-icon></v-btn
|
||||
>
|
||||
<div class="play-time" style="flex: 1 1 80px">
|
||||
{{ currentTime }} / {{ totalTime }}
|
||||
</div>
|
||||
<v-slider
|
||||
color="currentColor"
|
||||
track-color="#cccccc"
|
||||
class="play-progress"
|
||||
v-model="playheadPercent"
|
||||
style="flex: 1 1 100%; height: 30px"
|
||||
min="0"
|
||||
max="100"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from "../../plugins/utils";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
player: null,
|
||||
duration: 0,
|
||||
playPercent: 0,
|
||||
playTime: 0,
|
||||
playing: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.player = this.$refs.player;
|
||||
this.player.addEventListener("timeupdate", this.updateProgressBar);
|
||||
this.player.addEventListener("play", () => {
|
||||
this.playing = true;
|
||||
});
|
||||
this.player.addEventListener("pause", () => {
|
||||
this.playing = false;
|
||||
});
|
||||
this.player.addEventListener("ended", function () {
|
||||
this.pause();
|
||||
this.playing = false;
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
currentTime() {
|
||||
return util.formatDuration(this.playTime);
|
||||
},
|
||||
totalTime() {
|
||||
return util.formatDuration(this.duration);
|
||||
},
|
||||
playheadPercent: {
|
||||
get: function () {
|
||||
return this.playPercent;
|
||||
},
|
||||
set: function (percent) {
|
||||
if (this.player.src) {
|
||||
this.playPercent = percent;
|
||||
this.player.currentTime = (percent / 100) * this.player.duration;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
play() {
|
||||
if (this.player.src) {
|
||||
if (this.player.paused) {
|
||||
this.player.play();
|
||||
} else if (this.player.ended) {
|
||||
// restart
|
||||
this.player.currentTime = 0;
|
||||
this.player.play();
|
||||
}
|
||||
}
|
||||
},
|
||||
pause() {
|
||||
if (this.player.src) {
|
||||
this.player.pause();
|
||||
}
|
||||
},
|
||||
updateProgressBar() {
|
||||
if (this.player.duration > 0) {
|
||||
this.playPercent = Math.floor(
|
||||
(100 / this.player.duration) * this.player.currentTime
|
||||
);
|
||||
} else {
|
||||
this.playPercent = 0;
|
||||
}
|
||||
this.playTime = 1000 * this.player.currentTime;
|
||||
},
|
||||
updateDuration() {
|
||||
this.duration = 1000 * this.player.duration;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
function playPauseAudio() {
|
||||
if (player.src) {
|
||||
if (player.paused || player.ended) {
|
||||
// Change the button to a pause button
|
||||
changeButtonType(btnPlayPause, 'pause');
|
||||
player.play();
|
||||
}
|
||||
else {
|
||||
// Change the button to a play button
|
||||
changeButtonType(btnPlayPause, 'play');
|
||||
player.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the current media from playing, and return it to the start position
|
||||
function stopAudio() {
|
||||
if (player.src) {
|
||||
player.pause();
|
||||
if (player.currentTime) player.currentTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggles the media player's mute and unmute status
|
||||
function muteVolume() {
|
||||
if (player.src) {
|
||||
if (player.muted) {
|
||||
// Change the button to a mute button
|
||||
changeButtonType(btnMute, 'mute');
|
||||
player.muted = false;
|
||||
}
|
||||
else {
|
||||
// Change the button to an unmute button
|
||||
changeButtonType(btnMute, 'unmute');
|
||||
player.muted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replays the media currently loaded in the player
|
||||
function replayAudio() {
|
||||
if (player.src) {
|
||||
resetPlayer();
|
||||
player.play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Updates a button's title, innerHTML and CSS class
|
||||
function changeButtonType(btn, value) {
|
||||
btn.title = value;
|
||||
btn.innerHTML = value;
|
||||
btn.className = value;
|
||||
}
|
||||
|
||||
function resetPlayer() {
|
||||
progressBar.value = 0;
|
||||
//clear the current song
|
||||
player.src = '';
|
||||
// Move the media back to the start
|
||||
player.currentTime = 0;
|
||||
// Set the play/pause button to 'play'
|
||||
changeButtonType(btnPlayPause, 'play');
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<message-incoming v-bind="{...$props, ...$attrs}">
|
||||
<div class="audio-bubble">
|
||||
<audio controls :src="src">Audio file</audio>
|
||||
<div class="bubble audio-bubble">
|
||||
<audio-player :src="src">Audio file</audio-player>
|
||||
</div>
|
||||
</message-incoming>
|
||||
</template>
|
||||
|
|
@ -9,11 +9,12 @@
|
|||
<script>
|
||||
import attachmentMixin from "./attachmentMixin";
|
||||
import MessageIncoming from './MessageIncoming.vue';
|
||||
import AudioPlayer from './AudioPlayer.vue';
|
||||
|
||||
export default {
|
||||
extends: MessageIncoming,
|
||||
mixins: [attachmentMixin],
|
||||
components: { MessageIncoming }
|
||||
components: { MessageIncoming, AudioPlayer }
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
<template>
|
||||
<message-outgoing v-bind="{ ...$props, ...$attrs }">
|
||||
<div class="audio-bubble">
|
||||
<audio controls :src="src">Audio file</audio>
|
||||
<audio-player :src="src">Audio file</audio-player>
|
||||
</div>
|
||||
</message-outgoing>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import attachmentMixin from "./attachmentMixin";
|
||||
import AudioPlayer from './AudioPlayer.vue';
|
||||
import MessageOutgoing from "./MessageOutgoing.vue";
|
||||
|
||||
export default {
|
||||
extends: MessageOutgoing,
|
||||
components: { MessageOutgoing },
|
||||
components: { MessageOutgoing, AudioPlayer },
|
||||
mixins: [attachmentMixin],
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -565,6 +565,13 @@ class Util {
|
|||
return dayjs.duration(ms).format("HH:mm:ss");
|
||||
}
|
||||
|
||||
formatDuration(ms) {
|
||||
if (ms >= (60 * 60000)) {
|
||||
return dayjs.duration(ms).format("H:mm:ss");
|
||||
}
|
||||
return dayjs.duration(ms).format("m:ss");
|
||||
}
|
||||
|
||||
formatRecordStartTime(timestamp) {
|
||||
var then = dayjs(timestamp);
|
||||
return then.format('lll');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue