Initial implementation of message selection
This commit is contained in:
@@ -8,15 +8,6 @@ Row {
|
||||
spacing: theme.spacing / 2
|
||||
|
||||
readonly property string eventText: Utils.processedEventText(model)
|
||||
readonly property real lineHeight:
|
||||
! eventText.match(/<img .+\/?>/) && multiline ? 1.25 : 1.0
|
||||
readonly property bool multiline:
|
||||
(eventText.match(/(\n|<br\/?>)/) || []).length > 0 ||
|
||||
contentLabel.contentWidth < (
|
||||
contentLabel.implicitWidth -
|
||||
contentLabel.leftPadding -
|
||||
contentLabel.rightPadding
|
||||
)
|
||||
|
||||
Item {
|
||||
width: hideAvatar ? 0 : 48
|
||||
@@ -64,16 +55,17 @@ Row {
|
||||
textFormat: Text.StyledText
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: onRight ? Text.AlignRight : Text.AlignLeft
|
||||
lineHeight: eventContent.lineHeight
|
||||
|
||||
leftPadding: theme.spacing
|
||||
rightPadding: leftPadding
|
||||
topPadding: theme.spacing / 2 * lineHeight
|
||||
}
|
||||
|
||||
HRichLabel {
|
||||
HSelectableLabel {
|
||||
id: contentLabel
|
||||
width: parent.width
|
||||
container: selectableLabelContainer
|
||||
index: model.index
|
||||
|
||||
text: theme.chat.message.styleInclude +
|
||||
eventContent.eventText +
|
||||
@@ -87,14 +79,14 @@ Row {
|
||||
" <font size=" + theme.fontSize.small +
|
||||
"px>⏳</font>" : "")
|
||||
|
||||
lineHeight: eventContent.lineHeight
|
||||
color: theme.chat.message.body
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
|
||||
leftPadding: theme.spacing
|
||||
rightPadding: leftPadding
|
||||
topPadding: nameLabel.visible ? 0 : bottomPadding
|
||||
bottomPadding: theme.spacing / 2 * lineHeight
|
||||
bottomPadding: theme.spacing / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,95 +7,149 @@ Rectangle {
|
||||
|
||||
color: theme.chat.eventList.background
|
||||
|
||||
HListView {
|
||||
id: eventList
|
||||
clip: true
|
||||
Component.onCompleted: shortcuts.flickTarget = eventList
|
||||
|
||||
function canCombine(item, itemAfter) {
|
||||
if (! item || ! itemAfter) return false
|
||||
|
||||
return Boolean(
|
||||
! canTalkBreak(item, itemAfter) &&
|
||||
! canDayBreak(item, itemAfter) &&
|
||||
item.sender_id === itemAfter.sender_id &&
|
||||
Utils.minutesBetween(item.date, itemAfter.date) <= 5
|
||||
)
|
||||
}
|
||||
|
||||
function canTalkBreak(item, itemAfter) {
|
||||
if (! item || ! itemAfter) return false
|
||||
|
||||
return Boolean(
|
||||
! canDayBreak(item, itemAfter) &&
|
||||
Utils.minutesBetween(item.date, itemAfter.date) >= 20
|
||||
)
|
||||
}
|
||||
|
||||
function canDayBreak(item, itemAfter) {
|
||||
if (itemAfter && itemAfter.event_type == "RoomCreateEvent")
|
||||
return true
|
||||
|
||||
if (! item || ! itemAfter || ! item.date || ! itemAfter.date)
|
||||
return false
|
||||
|
||||
return item.date.getDate() != itemAfter.date.getDate()
|
||||
}
|
||||
|
||||
model: HListModel {
|
||||
keyField: "client_id"
|
||||
source:
|
||||
modelSources[["Event", chatPage.userId, chatPage.roomId]] || []
|
||||
}
|
||||
|
||||
property bool ownEventsOnRight:
|
||||
width < theme.chat.eventList.ownEventsOnRightUnderWidth
|
||||
|
||||
delegate: EventDelegate {}
|
||||
|
||||
HSelectableLabelContainer {
|
||||
id: selectableLabelContainer
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: theme.spacing
|
||||
anchors.rightMargin: theme.spacing
|
||||
reversed: eventList.verticalLayoutDirection == ListView.BottomToTop
|
||||
|
||||
topMargin: theme.spacing
|
||||
bottomMargin: theme.spacing
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
onDragPositionChanged: {
|
||||
let boost = 20 * (
|
||||
dragPosition.y < 50 ?
|
||||
-dragPosition.y : -(height - dragPosition.y)
|
||||
)
|
||||
|
||||
// Keep x scroll pages cached, to limit images having to be
|
||||
// reloaded from network.
|
||||
cacheBuffer: height * 4
|
||||
|
||||
// Declaring this as "alias" provides the on... signal
|
||||
property real yPos: visibleArea.yPosition
|
||||
property bool canLoad: true
|
||||
onYPosChanged: if (canLoad && yPos < 0.1) Qt.callLater(loadPastEvents)
|
||||
|
||||
function loadPastEvents() {
|
||||
// try/catch blocks to hide pyotherside error when the
|
||||
// component is destroyed but func is still running
|
||||
|
||||
try {
|
||||
eventList.canLoad = false
|
||||
|
||||
py.callClientCoro(
|
||||
chatPage.userId, "load_past_events", [chatPage.roomId],
|
||||
moreToLoad => {
|
||||
try {
|
||||
eventList.canLoad = moreToLoad
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
dragFlicker.speed =
|
||||
dragPosition.x == 0 && dragPosition.y == 0 ? 0 :
|
||||
dragPosition.y < 50 ? 1000 + boost:
|
||||
dragPosition.y > height - 50 ? -1000 + -boost :
|
||||
0
|
||||
}
|
||||
|
||||
property string inviter: chatPage.roomInfo.inviter || ""
|
||||
// When an invited room becomes joined, we should now be able to fetch
|
||||
// past events.
|
||||
onInviterChanged: canLoad = true
|
||||
Timer {
|
||||
id: dragFlicker
|
||||
interval: 100
|
||||
running: speed != 0
|
||||
repeat: true
|
||||
|
||||
onTriggered: {
|
||||
if (eventList.verticalOvershoot != 0) return
|
||||
if (speed < 0 && eventList.atYEnd) return
|
||||
if (eventList.atYBeggining) {
|
||||
if (bouncedStart) { return } else { bouncedStart = true }
|
||||
}
|
||||
|
||||
eventList.flick(0, speed * acceleration)
|
||||
acceleration = Math.min(8, acceleration * 1.05)
|
||||
}
|
||||
onRunningChanged: if (! running) {
|
||||
acceleration = 1.0
|
||||
bouncedStart = false
|
||||
eventList.cancelFlick()
|
||||
eventList.returnToBounds()
|
||||
}
|
||||
|
||||
property real speed: 0.0
|
||||
property real acceleration: 1.0
|
||||
property bool bouncedStart: false
|
||||
}
|
||||
|
||||
HListView {
|
||||
id: eventList
|
||||
clip: true
|
||||
enableFlicking: false
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: theme.spacing
|
||||
anchors.rightMargin: theme.spacing
|
||||
|
||||
topMargin: theme.spacing
|
||||
bottomMargin: theme.spacing
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
|
||||
// Keep x scroll pages cached, to limit images having to be
|
||||
// reloaded from network.
|
||||
cacheBuffer: height * 4
|
||||
|
||||
onYPosChanged:
|
||||
if (canLoad && yPos < 0.1) Qt.callLater(loadPastEvents)
|
||||
|
||||
// When an invited room becomes joined, we should now be able to
|
||||
// fetch past events.
|
||||
onInviterChanged: canLoad = true
|
||||
|
||||
Component.onCompleted: shortcuts.flickTarget = eventList
|
||||
|
||||
|
||||
property string inviter: chatPage.roomInfo.inviter || ""
|
||||
property real yPos: visibleArea.yPosition
|
||||
property bool canLoad: true
|
||||
|
||||
property bool ownEventsOnRight:
|
||||
width < theme.chat.eventList.ownEventsOnRightUnderWidth
|
||||
|
||||
|
||||
function canCombine(item, itemAfter) {
|
||||
if (! item || ! itemAfter) return false
|
||||
|
||||
return Boolean(
|
||||
! canTalkBreak(item, itemAfter) &&
|
||||
! canDayBreak(item, itemAfter) &&
|
||||
item.sender_id === itemAfter.sender_id &&
|
||||
Utils.minutesBetween(item.date, itemAfter.date) <= 5
|
||||
)
|
||||
}
|
||||
|
||||
function canTalkBreak(item, itemAfter) {
|
||||
if (! item || ! itemAfter) return false
|
||||
|
||||
return Boolean(
|
||||
! canDayBreak(item, itemAfter) &&
|
||||
Utils.minutesBetween(item.date, itemAfter.date) >= 20
|
||||
)
|
||||
}
|
||||
|
||||
function canDayBreak(item, itemAfter) {
|
||||
if (itemAfter && itemAfter.event_type == "RoomCreateEvent")
|
||||
return true
|
||||
|
||||
if (! item || ! itemAfter || ! item.date || ! itemAfter.date)
|
||||
return false
|
||||
|
||||
return item.date.getDate() != itemAfter.date.getDate()
|
||||
}
|
||||
|
||||
function loadPastEvents() {
|
||||
// try/catch blocks to hide pyotherside error when the
|
||||
// component is destroyed but func is still running
|
||||
|
||||
try {
|
||||
eventList.canLoad = false
|
||||
|
||||
py.callClientCoro(
|
||||
chatPage.userId, "load_past_events", [chatPage.roomId],
|
||||
moreToLoad => {
|
||||
try {
|
||||
eventList.canLoad = moreToLoad
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
model: HListModel {
|
||||
keyField: "client_id"
|
||||
source: modelSources[[
|
||||
"Event", chatPage.userId, chatPage.roomId
|
||||
]] || []
|
||||
}
|
||||
|
||||
delegate: EventDelegate {}
|
||||
}
|
||||
}
|
||||
|
||||
HNoticePage {
|
||||
|
Reference in New Issue
Block a user