Start on voice recording

This commit is contained in:
N-Pex 2021-02-22 16:34:19 +01:00
parent 3aef5b6b3e
commit fd86e753fe
7 changed files with 335 additions and 2 deletions

View file

@ -154,6 +154,21 @@
/>
</v-col>
<v-col
class="input-area-button text-center flex-grow-0 flex-shrink-1"
>
<v-btn
fab
small
elevation="0"
color="transparent"
v-blur
style="z-index:10"
@mousedown.stop="startRecording"
>
<v-icon :color="showRecorder ? 'white' : 'black'">mic</v-icon>
</v-btn>
</v-col>
<v-col
class="input-area-button text-center flex-grow-0 flex-shrink-1"
v-if="editedEvent || replyToEvent"
@ -183,6 +198,7 @@
</v-btn>
</v-col>
</v-row>
<VoiceRecorder :show="showRecorder" v-on:close="showRecorder = false" v-on:file="onVoiceRecording" />
</v-container>
<div v-if="currentImageInput">
@ -271,6 +287,7 @@ import DebugEvent from "./messages/DebugEvent.vue";
import util from "../plugins/utils";
import MessageOperations from "./messages/MessageOperations.vue";
import ChatHeader from "./ChatHeader";
import VoiceRecorder from "./VoiceRecorder";
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
@ -320,6 +337,7 @@ export default {
RoomAvatarChanged,
DebugEvent,
MessageOperations,
VoiceRecorder
},
data() {
@ -341,6 +359,7 @@ export default {
showContextMenu: false,
showContextMenuAnchor: null,
initialLoadDone: false,
showRecorder: false,
/**
* Current chat container size. We need to keep track of this so that if and when
@ -1061,6 +1080,19 @@ export default {
dayForEvent(event) {
return util.formatDay(event.getTs());
},
startRecording() {
this.showRecorder = true;
},
onVoiceRecording(event) {
util.sendImage(
this.$matrix.matrixClient,
this.roomId,
event.file,
undefined
);
}
},
};
</script>

View file

@ -0,0 +1,163 @@
<template>
<div
v-show="show"
:class="{ 'voice-recorder': true, 'will-cancel': willCancel }"
ref="vr_root"
>
<v-container fluid fill-height>
<v-row align="center" justify="center">
<v-col class="text-center">
<div class="recording-time">
{{ recordingTime }}
</div>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
const State = {
INITIAL: "intial",
RECORDING: "recording",
RECORDED: "recorded",
ERROR: "error",
};
import util from "../plugins/utils";
export default {
name: "VoiceRecorder",
props: {
show: {
type: Boolean,
default: function () {
return false;
},
},
},
data() {
return {
willCancel: false,
states: State,
state: State.INITIAL,
recordStartedAt: null,
recordingTime: null,
recordTimer: null,
};
},
watch: {
show(val) {
if (val) {
// Add listeners
document.addEventListener("mouseup", this.mouseUp, false);
document.addEventListener("mousemove", this.mouseMove, false);
this.startRecording();
} else {
// Remove listeners
document.removeEventListener("mouseup", this.mouseUp, false);
document.removeEventListener("mousemove", this.mouseMove, false);
}
},
},
methods: {
close() {
this.stopRecordTimer();
this.$emit("close");
},
mouseUp(ignoredEvent) {
document.removeEventListener("mouseup", this.mouseUp, false);
document.removeEventListener("mousemove", this.mouseMove, false);
document.body.style.cursor = "";
if (this.willCancel) {
this.cancelRecording();
} else {
this.stopRecording();
}
this.close();
},
mouseMove(event) {
document.body.style.cursor = "ns-resize";
let rect = this.$refs.vr_root.getBoundingClientRect();
this.willCancel = event.clientY < rect.top;
console.log(
"Cancel: " + this.willCancel + " " + event.clientY + " " + rect.top
);
// let bottom = rect.bottom;
// let mouseBottom = event.clientY;
// let newHeight = Math.max(
// 200,
// Math.min(0.7 * window.innerHeight, bottom - mouseBottom)
// );
// this.$refs.chatPane.style.height = newHeight + "px";
event.preventDefault();
event.stopPropagation();
},
startRecording() {
const MicRecorder = require("mic-recorder-to-mp3");
// Start recording. Browser will request permission to use your microphone.
this.recorder = new MicRecorder({
bitRate: 128,
});
this.recorder
.start()
.then(() => {
this.state = State.RECORDING;
this.recordStartedAt = Date.now();
this.startRecordTimer();
})
.catch((e) => {
console.error(e);
//this.state = State.ERROR;
});
},
cancelRecording() {
this.state = State.INITIAL;
this.recorder.stop();
this.stopRecordTimer();
},
stopRecording() {
this.state = State.RECORDED;
this.stopRecordTimer();
this.recorder
.stop()
.getMp3()
.then(([buffer, blob]) => {
// do what ever you want with buffer and blob
// Example: Create a mp3 file and play
const file = new File(buffer, util.formatRecordStartTime(this.recordStartedAt) + ".mp3", {
type: blob.type,
lastModified: Date.now(),
});
this.$emit("file", {file: file});
// const player = new Audio(URL.createObjectURL(file));
// player.play();
})
.catch((e) => {
alert("We could not retrieve your message");
console.log(e);
});
},
startRecordTimer() {
this.stopRecordTimer();
this.recordTimer = setInterval(() => {
const now = Date.now();
this.recordingTime = util.formatRecordDuration(
now - this.recordStartedAt
);
}, 500);
},
stopRecordTimer() {
if (this.recordTimer) {
clearInterval(this.recordTimer);
this.recordTimer = null;
this.recordingTime = null;
}
},
},
};
</script>
<style lang="scss">
@import "@/assets/css/chat.scss";
</style>