linphone-desktop/linphone-app/ui/modules/Linphone/Chat/ChatAudioPreview.qml
Julien Wadel 839a1bc9b0 - Send multiple files in one message, with preview.
- Message preview manage huge heights.
- Chat design rework.
- Sort timelines by unread chat rooms.
- Fix thumbnails that weren't deleted.
- Play audio record on playback device instead of ringer device.
- Fix binding loops on scrollable areas.
- Change timeline filter to a minimal version.
- Fix record button hovering.
- Fix camera button in fullscreen.
2022-03-08 15:44:50 +01:00

173 lines
No EOL
5.1 KiB
QML

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
import Utils 1.0
import UtilsCpp 1.0
import LinphoneEnums 1.0
import Units 1.0
import 'Chat.js' as Logic
// =============================================================================
Rectangle{
id: audioPreviewBlock
property bool haveRecorder: RecorderManager.haveVocalRecorder
property RecorderModel vocalRecorder : (haveRecorder ? RecorderManager.getVocalRecorder() : null)
property bool isRecording : (vocalRecorder ? vocalRecorder.state != LinphoneEnums.RecorderStateClosed : false)
property bool isPlaying : vocalPlayer.item && vocalPlayer.item.playbackState === SoundPlayer.PlayingState
onIsRecordingChanged: if(isRecording) {
mediaProgressBar.resume()
}else
mediaProgressBar.stop()
onIsPlayingChanged: isPlaying ? mediaProgressBar.resume() : mediaProgressBar.stop()
Layout.preferredHeight: visible ? ChatAudioPreviewStyle.height : 0
color: ChatAudioPreviewStyle.backgroundColor
radius: 0
state: haveRecorder ? 'showed' : 'hidden'
clip: false
Loader {
id: vocalPlayer
active: haveRecorder && vocalRecorder && !isRecording
sourceComponent: SoundPlayer {
source: (haveRecorder && vocalRecorder? vocalRecorder.file : '')
onStopped:{
mediaProgressBar.value = 101
}
Component.onCompleted: {
play()// This will open the file and allow seeking
pause()
mediaProgressBar.value = 101
mediaProgressBar.refresh()
}
}
}
RowLayout{
id: lineLayout
anchors.fill: parent
spacing: 0
ActionButton{
Layout.preferredHeight: iconSize
Layout.preferredWidth: iconSize
Layout.leftMargin: 6
Layout.alignment: Qt.AlignVCenter
isCustom: true
colorSet: ChatAudioPreviewStyle.deleteAction
onClicked: RecorderManager.clearVocalRecorder()
}
VuMeter {
Layout.leftMargin: 6
Layout.rightMargin: 6
Timer {
interval: 50
repeat: true
running: audioPreviewBlock.isRecording
onTriggered: parent.value = audioPreviewBlock.vocalRecorder.getCaptureVolume()
}
visible: audioPreviewBlock.isRecording
}
Item{
Layout.fillHeight: true
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: 10
Layout.bottomMargin: 10
Layout.leftMargin: 6
MediaProgressBar{
id: mediaProgressBar
anchors.fill: parent
waveLeftMargin: !vocalPlayer.item && vocalRecorder ? 10 : 0
progressDuration: !vocalPlayer.item && vocalRecorder? vocalRecorder.getDuration() : 0
progressPosition: !vocalPlayer.item ? progressDuration : 0
value: !vocalPlayer.item ? 0.01 * progressDuration / 5 : 100
stopAtEnd: !audioPreviewBlock.isRecording
resetAtEnd: false
colorSet: isRecording ? ChatAudioPreviewStyle.recordingProgressionWave : ChatAudioPreviewStyle.progressionWave
function progressComputation(t) {
return 1 * Math.sqrt(1 - (t=t/1-1)*t);
}
function refresh(){
if( vocalPlayer.item){
progressPosition = vocalPlayer.item.getPosition()
value = 100 * ( progressPosition / vocalPlayer.item.duration)
}else{// Recording
progressDuration = vocalRecorder.getDuration()
progressPosition = progressDuration
if( value == 0)
value = 1
else
value = value + Math.pow(value,-0.7)
}
}
onEndReached:{
if(vocalPlayer.item)
vocalPlayer.item.stop()
}
onRefreshPositionRequested: refresh()
onSeekRequested: if( vocalPlayer.item){
vocalPlayer.item.seek(ms)
progressPosition = vocalPlayer.item.getPosition()
value = 100 * (progressPosition / vocalPlayer.item.duration)
}
}
}
ActionButton{
Layout.preferredHeight: iconSize
Layout.preferredWidth: iconSize
Layout.rightMargin: ChatStyle.rightButtonMargin
Layout.leftMargin: ChatStyle.rightButtonLMargin
Layout.alignment: Qt.AlignVCenter
isCustom: true
colorSet: audioPreviewBlock.isRecording ? ChatAudioPreviewStyle.stopAction
: (audioPreviewBlock.isPlaying ? ChatAudioPreviewStyle.pauseAction
: ChatAudioPreviewStyle.playAction)
onClicked:{
if(audioPreviewBlock.isRecording){// Stop the record and save the file
audioPreviewBlock.vocalRecorder.stop()
mediaProgressBar.value = 0
}else if(audioPreviewBlock.isPlaying){// Pause the play
vocalPlayer.item.pause()
}else{// Play the audio
vocalPlayer.item.play()
}
}
}
}
states: [
State {
name: "hidden"
PropertyChanges { target: audioPreviewBlock; opacity: 0 ; visible: false }
},
State {
name: "showed"
PropertyChanges { target: audioPreviewBlock; opacity: 1 ; visible: true }
}
]
transitions: [
Transition {
from: "*"; to: "showed"
SequentialAnimation{
ScriptAction{ script: audioPreviewBlock.visible = true }
ScriptAction{ script: audioPreviewBlock.vocalRecorder.start() }
NumberAnimation{ properties: "opacity"; easing.type: Easing.OutBounce; duration: 250 }
}
},
Transition {
from: "*"; to: "hidden"
SequentialAnimation{
NumberAnimation{ properties: "opacity"; duration: 250 }
ScriptAction{ script: audioPreviewBlock.visible = false }
}
}
]
}