add emojiPicker and microphone
This commit is contained in:
parent
d3031a1e70
commit
fb707fcde3
@ -34,6 +34,7 @@
|
|||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^7.5.0",
|
"eslint-plugin-vue": "^7.5.0",
|
||||||
"node-sass": "^5.0.0",
|
"node-sass": "^5.0.0",
|
||||||
|
"recorder-js": "*",
|
||||||
"sass-loader": "^10.1.1",
|
"sass-loader": "^10.1.1",
|
||||||
"vue-router": "^3.4.9",
|
"vue-router": "^3.4.9",
|
||||||
"vue-template-compiler": "^2.6.11"
|
"vue-template-compiler": "^2.6.11"
|
||||||
|
1
public/sym/ic_insert_emoticon_white.svg
Normal file
1
public/sym/ic_insert_emoticon_white.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></svg>
|
After (image error) Size: 510 B |
1
public/sym/ic_mic_white.svg
Normal file
1
public/sym/ic_mic_white.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></svg>
|
After (image error) Size: 348 B |
@ -1,22 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="newMessageBanner" ref="newMessageBanner">
|
<div class="newMessageBanner" ref="newMessageBanner">
|
||||||
<reply-event v-if="replyTo" :event="replyTo" @click.native="resetReplyTo()"/>
|
<reply-event v-if="replyTo" :event="replyTo" @click.native="resetReplyTo()"/>
|
||||||
<form v-on:submit.prevent="sendMessage()">
|
<form v-on:submit.prevent="sendMessage()">
|
||||||
<textarea
|
<textarea
|
||||||
@keyup.enter.exact="sendMessage()"
|
@keyup.enter.exact="sendMessage()"
|
||||||
@input="resizeMessageBanner(); sendTyping(2000);"
|
@input="resizeMessageBanner(); sendTyping(2000);"
|
||||||
v-model="event.content.body"
|
v-model="event.content.body"
|
||||||
ref="newMessageInput" class="newMessageInput"
|
ref="newMessageInput" class="newMessageInput"
|
||||||
rows="1" placeholder="type a message ..."
|
rows="1" placeholder="type a message ..."
|
||||||
/>
|
/>
|
||||||
|
<icon
|
||||||
|
v-if="event.content.body && !isRecording"
|
||||||
|
type="submit"
|
||||||
|
title="press enter to submit"
|
||||||
|
class="sendMessageBtn"
|
||||||
|
ic="./sym/ic_send_white.svg"
|
||||||
|
/>
|
||||||
|
<div v-else class="recorder">
|
||||||
|
<icon
|
||||||
|
v-if="!isRecording"
|
||||||
|
title="record voice"
|
||||||
|
class="recordBtn start"
|
||||||
|
ic="./sym/ic_mic_white.svg"
|
||||||
|
@click.native="startRecording()"
|
||||||
|
ref="startRecord"
|
||||||
|
/>
|
||||||
|
<div v-else class="voiceMeterContainer">
|
||||||
|
<div class="voiceMeter" ref="voiceMeter"></div>
|
||||||
|
<icon
|
||||||
|
title="record voice"
|
||||||
|
class="recordBtn stop"
|
||||||
|
ic="./sym/ic_mic_white.svg"
|
||||||
|
@click.native="stopRecording()"
|
||||||
|
ref="stopRecord"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<icon
|
<icon
|
||||||
type="submit"
|
title="toggle emoji"
|
||||||
title="press enter to submit"
|
class="emojiToggle"
|
||||||
class="sendMessageBtn"
|
ic="./sym/ic_insert_emoticon_white.svg"
|
||||||
ic="./sym/ic_send_white.svg"
|
@click.native="toggleEmojiPicker()"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</form>
|
<v-emoji-picker
|
||||||
</div>
|
v-if="showEmojiPicker"
|
||||||
|
class="emojiPicker"
|
||||||
|
@select="onSelectEmoji"
|
||||||
|
:dark="true"
|
||||||
|
:continuousList="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -25,12 +60,16 @@ import {matrix} from '@/main.js';
|
|||||||
import {parseMessage} from '@/lib/eventUtils';
|
import {parseMessage} from '@/lib/eventUtils';
|
||||||
import {calcUserName} from '@/lib/matrixUtils';
|
import {calcUserName} from '@/lib/matrixUtils';
|
||||||
import ReplyEvent from '@/components/replyEvent';
|
import ReplyEvent from '@/components/replyEvent';
|
||||||
|
import {VEmojiPicker} from 'v-emoji-picker';
|
||||||
|
import Recorder from 'recorder-js';
|
||||||
|
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'newMessage',
|
name: 'newMessage',
|
||||||
components: {
|
components: {
|
||||||
ReplyEvent,
|
ReplyEvent,
|
||||||
icon
|
icon,
|
||||||
|
VEmojiPicker
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
onResize: Function,
|
onResize: Function,
|
||||||
@ -69,6 +108,26 @@ export default {
|
|||||||
onSelectEmoji(emoji) {
|
onSelectEmoji(emoji) {
|
||||||
this.event.content.body += emoji.data;
|
this.event.content.body += emoji.data;
|
||||||
},
|
},
|
||||||
|
startRecording(){
|
||||||
|
navigator.mediaDevices.getUserMedia({audio: true})
|
||||||
|
.then(stream => {
|
||||||
|
this.recorder.init(stream);
|
||||||
|
this.recorder.start().then(()=>this.isRecording=true);
|
||||||
|
})
|
||||||
|
.catch(err => console.log('unable to get stream', err));
|
||||||
|
},
|
||||||
|
stopRecording(){
|
||||||
|
this.recorder.stop()
|
||||||
|
.then(({blob}) => {
|
||||||
|
this.recBlob = blob;
|
||||||
|
this.isRecording=false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setVoiceMeter(value){
|
||||||
|
if (!this.$refs.stopRecord) return;
|
||||||
|
this.$refs.voiceMeter.style.height = `calc(3rem + ${value/4}px`;
|
||||||
|
this.$refs.voiceMeter.style.width = `calc(3rem + ${value/4}px`;
|
||||||
|
},
|
||||||
parseMessage,
|
parseMessage,
|
||||||
calcUserName
|
calcUserName
|
||||||
},
|
},
|
||||||
@ -87,7 +146,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
showEmojiPicker: false,
|
showEmojiPicker: false,
|
||||||
waitForSendTyping: false
|
waitForSendTyping: false,
|
||||||
|
recorder: new Recorder(audioContext, {
|
||||||
|
onAnalysed: data => this.setVoiceMeter(data.lineTo)
|
||||||
|
}),
|
||||||
|
isRecording: false,
|
||||||
|
recBlob: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +173,7 @@ export default {
|
|||||||
margin-top: 1.25rem;
|
margin-top: 1.25rem;
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
left: 1rem;
|
left: 3rem;
|
||||||
min-height: 1.5rem;
|
min-height: 1.5rem;
|
||||||
max-height: 10rem;
|
max-height: 10rem;
|
||||||
width: calc(100% - 7rem);
|
width: calc(100% - 7rem);
|
||||||
@ -144,4 +208,58 @@ export default {
|
|||||||
.username{
|
.username{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.emojiPicker{
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% + 0.25rem);
|
||||||
|
left: 0.25rem;
|
||||||
|
z-index: 10;
|
||||||
|
max-width: calc(100% - 0.5rem - 2px);
|
||||||
|
}
|
||||||
|
.emojiToggle{
|
||||||
|
position: absolute;
|
||||||
|
left: 0.25rem;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
background-color: unset;
|
||||||
|
height: 2.5rem;
|
||||||
|
width: 2.5rem;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.recordBtn{
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
bottom: 0.25rem;
|
||||||
|
background-color: #1d1d1d;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.recordBtn.stop{
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #c63e3e;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.voiceMeter{
|
||||||
|
position: absolute;
|
||||||
|
background-color: #fff;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 3px 3px 10px #111;
|
||||||
|
}
|
||||||
|
.voiceMeterContainer{
|
||||||
|
position: absolute;
|
||||||
|
height: 3rem;
|
||||||
|
width: 3rem;
|
||||||
|
bottom: 0.25rem;
|
||||||
|
right: 1rem;
|
||||||
|
}
|
||||||
|
.recorder{
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 8rem;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
border-radius: 0 1rem 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue
Block a user