linphone-desktop/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml
Julien Wadel 3aab79261e - Chat room loading optimization.
- Fix loading more chat entries when going to beginning.
- Fix right padding text in chat messages.
- Fix black screen videos.
2022-01-26 15:37:08 +01:00

357 lines
12 KiB
QML

import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.5
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
import ColorsList 1.0
import UtilsCpp 1.0
import 'Timeline.js' as Logic
// =============================================================================
Rectangle {
id: timeline
// ---------------------------------------------------------------------------
property alias model: view.model
property string _selectedSipAddress
property bool showHistoryButton : true
property bool updateSelectionModels : true
property bool isFilterVisible: searchView.visible || filterView.visible
// ---------------------------------------------------------------------------
//signal entrySelected (string entry)
signal entrySelected (TimelineModel entry)
signal entryClicked(TimelineModel entry)
signal showHistoryRequest()
// ---------------------------------------------------------------------------
color: TimelineStyle.color
ColumnLayout {
anchors.fill: parent
spacing: 0
// -------------------------------------------------------------------------
Connections {
target: model
onSelectedCountChanged:{
if(selectedCount<=0) {
view.currentIndex = -1
timeline.entrySelected('')
}
}
onSelectedChanged : if(timelineModel && timeline.updateSelectionModels) timeline.entrySelected(timelineModel)
}
// -------------------------------------------------------------------------
// Legend.
// -------------------------------------------------------------------------
Rectangle {
id: legendArea
Layout.fillWidth: true
Layout.preferredHeight: TimelineStyle.legend.height
Layout.alignment: Qt.AlignTop
color: showHistory.containsMouse?TimelineStyle.legend.backgroundColor.hovered:TimelineStyle.legend.backgroundColor.normal
visible:view.count > 0 || timeline.isFilterVisible || timeline.model.filterFlags > 0
MouseArea{// no more showing history
id:showHistory
anchors.fill:parent
onClicked: {
filterView.visible = !filterView.visible
}
}
RowLayout{
anchors.fill:parent
spacing:TimelineStyle.legend.spacing
Text {
Layout.preferredHeight: parent.height
Layout.fillWidth: true
Layout.leftMargin: TimelineStyle.legend.leftMargin
color: TimelineStyle.legend.color
font.pointSize: TimelineStyle.legend.pointSize
//: A title for filtering mode.
text: qsTr('timelineFilter')+' : '
+(timeline.model.filterFlags == 0 || timeline.model.filterFlags == TimelineProxyModel.AllChatRooms
//: 'All' The mode for timelines filtering.
? qsTr('timelineFilterAll')
//: 'Custom' The mode for timelines filtering.
: qsTr('timelineFilterCustom'))
verticalAlignment: Text.AlignVCenter
}
Icon {
id:filterButton
Layout.alignment: Qt.AlignRight
icon: 'filter_params_custom'
iconSize: TimelineStyle.legend.iconSize
overwriteColor: TimelineStyle.legend.color
MouseArea{
anchors.fill:parent
onClicked:{
filterView.visible = !filterView.visible
}
}
}
MouseArea{
Layout.alignment: Qt.AlignRight
Layout.fillHeight: true
Layout.preferredWidth: TimelineStyle.legend.iconSize
onClicked:{
searchView.visible = !searchView.visible
}
Icon {
id:searchButton
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
property bool searching: searchView.visible
icon: (searchView.visible? 'close_custom': 'search_custom')
iconSize: TimelineStyle.legend.iconSize
overwriteColor: TimelineStyle.legend.color
}
}
MouseArea{
Layout.alignment: Qt.AlignRight
Layout.rightMargin: TimelineStyle.legend.lastRightMargin
Layout.fillHeight: true
Layout.preferredWidth: TimelineStyle.legend.iconSize
visible: timeline.showHistoryButton
onClicked:{
showHistoryRequest()
}
Icon {
id:callHistoryButton
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
property bool searching: searchView.visible
icon: 'call_history_custom'
iconSize: TimelineStyle.legend.iconSize
overwriteColor: TimelineStyle.legend.color
}
}
}
}
// -------------------------------------------------------------------------
// Filter.
// -------------------------------------------------------------------------
Rectangle{
id:filterView
Layout.fillWidth: true
Layout.preferredHeight: filterChoices.height
Layout.alignment: Qt.AlignCenter
border.color: TimelineStyle.filterField.borderColor
border.width: 2
visible:false
ColumnLayout{
id:filterChoices
anchors.leftMargin: 20
anchors.left:parent.left
anchors.right:parent.right
spacing:-4
function getFilterFlags(){
return secureFilter.model.get(secureFilter.currentIndex).value | groupFilter.model.get(groupFilter.currentIndex).value | ephemeralsFilter.model.get(ephemeralsFilter.currentIndex).value;
}
ComboBox {
Layout.fillWidth: true
id:secureFilter
currentIndex: 0
textRole: "key"
model: ListModel {
ListElement {
//: 'All security levels' : Filter item. Selecting it will not do any filter on security level.
key: qsTr('timelineFilterAllSecureLevelRooms'); value: 0}
ListElement {
//: 'Standard rooms' : Filter item. Selecting it will show all simple rooms.
key: qsTr('timelineFilterStandardRooms'); value: TimelineProxyModel.StandardChatRoom}
ListElement {
//: 'Secure rooms' : Filter item. Selecting it will show all secure rooms.
key: qsTr('timelineFilterSecureRooms'); value: TimelineProxyModel.SecureChatRoom}
}
haveBorder: false
haveMargin: false
backgroundColor: 'transparent'
visible: SettingsModel.secureChatEnabled && SettingsModel.standardChatEnabled
onActivated: timeline.model.filterFlags = filterChoices.getFilterFlags()
}
ComboBox {
Layout.fillWidth: true
id:groupFilter
currentIndex: 0
textRole: "key"
model: ListModel {
ListElement {
//: 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations.
key: qsTr('timelineFilterAnyChatRooms'); value: 0}
ListElement {
//: 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant).
key: qsTr('timelineFilterSimpleRooms'); value: TimelineProxyModel.SimpleChatRoom}
ListElement {
//: 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant).
key: qsTr('timelineFilterChatGroups'); value: TimelineProxyModel.GroupChatRoom}
}
haveBorder: false
haveMargin: false
backgroundColor: 'transparent'
visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled
onActivated: timeline.model.filterFlags = filterChoices.getFilterFlags()
}
ComboBox {
Layout.fillWidth: true
id:ephemeralsFilter
currentIndex: 0
textRole: "key"
model: ListModel {
ListElement {
//: 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation.
key: qsTr('timelineFilterAnyEphemerals'); value: 0}
ListElement {
//: 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled.
key: qsTr('timelineFilterNoEphemerals'); value: TimelineProxyModel.NoEphemeralChatRoom}
ListElement {
//: 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled.
key: qsTr('timelineFilterEphemerals'); value: TimelineProxyModel.EphemeralChatRoom}
}
haveBorder: false
haveMargin: false
backgroundColor: 'transparent'
visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled
onActivated: timeline.model.filterFlags = filterChoices.getFilterFlags()
}
}
}
// -------------------------------------------------------------------------
// Search.
// -------------------------------------------------------------------------
Rectangle{
id:searchView
Layout.fillWidth: true
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignCenter
border.color: TimelineStyle.searchField.borderColor
border.width: 2
visible:false
onVisibleChanged: if(visible){
timeline.model.filterText = searchBar.text
searchBar.forceActiveFocus()
}else{
timeline.model.filterText = ''
}
TextField {
id:searchBar
anchors.fill: parent
anchors.rightMargin: 7
anchors.leftMargin: 7
anchors.topMargin: 5
anchors.bottomMargin: 5
width: parent.width - 14
icon: 'search_custom'
iconSize: 30
overwriteColor: TimelineStyle.searchField.color
//: 'Search in the list' : ths is a placeholder when searching something in the timeline list
placeholderText: qsTr('timelineSearchPlaceholderText')
onTextChanged: timeline.model.filterText = text
font.pointSize: TimelineStyle.searchField.pointSize
}
}
// -------------------------------------------------------------------------
// History.
// -------------------------------------------------------------------------
ScrollableListView {
id: view
property alias updateSelectionModels: timeline.updateSelectionModels
Layout.fillHeight: true
Layout.fillWidth: true
currentIndex: -1
delegate: Item {
height: TimelineStyle.contact.height
width: parent ? parent.width : 0
Contact {
id: contactView
property bool isSelected: modelData != undefined && modelData.selected //view.currentIndex === index
anchors.fill: parent
color: isSelected
? TimelineStyle.contact.backgroundColor.selected
: (
index % 2 == 0
? TimelineStyle.contact.backgroundColor.a
: TimelineStyle.contact.backgroundColor.b
)
displayUnreadMessageCount: SettingsModel.standardChatEnabled || SettingsModel.secureChatEnabled
entry: modelData.chatRoomModel
sipAddressColor: isSelected
? TimelineStyle.contact.sipAddress.color.selected
: TimelineStyle.contact.sipAddress.color.normal
usernameColor: isSelected
? TimelineStyle.contact.username.color.selected
: TimelineStyle.contact.username.color.normal
TooltipArea {
id: contactTooltip
text: UtilsCpp.toDateTimeString(modelData.chatRoomModel.lastUpdateTime)
isClickable: true
}
Icon{
icon: TimelineStyle.ephemeralTimer.icon
iconSize: TimelineStyle.ephemeralTimer.iconSize
overwriteColor: modelData && modelData.selected ? TimelineStyle.ephemeralTimer.selectedTimerColor : TimelineStyle.ephemeralTimer.timerColor
anchors.right:parent.right
anchors.bottom:parent.bottom
anchors.bottomMargin: 7
anchors.rightMargin: 7
visible: modelData.chatRoomModel.ephemeralEnabled
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
propagateComposedEvents: true
preventStealing: false
onClicked: {
if(mouse.button == Qt.LeftButton){
//if(modelData.selected || !view.updateSelectionModels)// Update selection
timeline.entryClicked(modelData)
if(view){
if(view.updateSelectionModels)
modelData.selected = true
view.currentIndex = index;
}
}else{
contactTooltip.show()
}
}
}
Connections{
target:modelData
onSelectedChanged:{
if(view.updateSelectionModels && selected) {
view.currentIndex = index;
}
}
}
}
}
}
}