2020-11-05 16:05:33 +03:00
/ *
Copyright ( C ) 2020 Sebastian J . Wolf and other contributors
This file is part of Fernschreiber .
Fernschreiber is free software: you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Fernschreiber is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Fernschreiber . If not , see < http: //www.gnu.org/licenses/>.
* /
import QtQuick 2.6
import Sailfish . Silica 1.0
2021-01-15 12:55:34 +03:00
import "./messageContent"
2020-11-05 16:05:33 +03:00
import "../js/twemoji.js" as Emoji
import "../js/functions.js" as Functions
2020-11-20 23:58:26 +03:00
import "../js/debug.js" as Debug
2020-11-05 16:05:33 +03:00
ListItem {
id: messageListItem
contentHeight: messageBackground . height + Theme . paddingMedium
2020-12-06 07:38:03 +03:00
property var chatId
property var messageId
2021-01-08 05:14:31 +03:00
property int messageIndex
2021-01-31 23:08:39 +03:00
property int messageViewCount
2020-12-06 07:38:03 +03:00
property var myMessage
2020-12-15 21:15:12 +03:00
property bool canReplyToMessage
2020-12-25 15:50:13 +03:00
readonly property bool isAnonymous: myMessage . sender [ "@type" ] === "messageSenderChat"
2020-12-07 23:43:09 +03:00
readonly property var userInformation: tdLibWrapper . getUserInformation ( myMessage . sender . user_id )
2020-11-07 22:58:23 +03:00
property QtObject precalculatedValues: ListView . view . precalculatedValues
2020-11-08 22:37:17 +03:00
readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme . primaryColor
readonly property int textAlign: isOwnMessage ? Text.AlignRight : Text . AlignLeft
readonly property Page page: precalculatedValues . page
2020-11-15 01:50:12 +03:00
readonly property bool isSelected: messageListItem . precalculatedValues . pageIsSelecting && page . selectedMessages . some ( function ( existingMessage ) {
2020-12-06 07:38:03 +03:00
return existingMessage . id === messageId
2020-11-15 01:50:12 +03:00
} ) ;
2020-12-07 23:43:09 +03:00
readonly property bool isOwnMessage: page . myUserId === myMessage . sender . user_id
2021-12-05 04:25:24 +03:00
readonly property bool canDeleteMessage: myMessage . can_be_deleted_for_all_users || ( myMessage . can_be_deleted_only_for_self && myMessage . chat_id === page . myUserId )
2021-01-15 12:55:34 +03:00
property bool hasContentComponent
2021-02-16 23:36:29 +03:00
property bool additionalOptionsOpened
2020-11-07 22:58:23 +03:00
2021-12-05 04:25:24 +03:00
readonly property var additionalItemsModel: ( extraContentLoader . item && ( "extraContextMenuItems" in extraContentLoader . item ) ) ?
extraContentLoader.item.extraContextMenuItems : 0
readonly property int numberOfExtraOptionsOtherThanDeleteMessage:
( showCopyMessageToClipboardMenuItem ? 0 : 1 ) +
( showForwardMessageMenuItem ? 0 : 1 ) +
( page . canPinMessages ( ) ? 1 : 0 ) +
( additionalItemsModel ? additionalItemsModel.length : 0 )
readonly property bool deleteMessageIsOnlyExtraOption: canDeleteMessage && ! numberOfExtraOptionsOtherThanDeleteMessage
readonly property int maxContextMenuItemCount: page . isPortrait ? 5 : 4
readonly property int baseContextMenuItemCount: ( canReplyToMessage ? 1 : 0 ) +
( myMessage . can_be_edited ? 1 : 0 ) + 2 /* "Select Message" and "More Options..." */
readonly property bool showCopyMessageToClipboardMenuItem: ( baseContextMenuItemCount + 1 ) <= maxContextMenuItemCount
readonly property bool showForwardMessageMenuItem: ( baseContextMenuItemCount + 2 ) <= maxContextMenuItemCount
// And don't count "More Options..." for "Delete Message" if "Delete Message" is the only extra option
readonly property bool haveSpaceForDeleteMessageMenuItem: ( baseContextMenuItemCount + 3 - ( deleteMessageIsOnlyExtraOption ? 1 : 0 ) ) <= maxContextMenuItemCount
2021-02-16 23:36:29 +03:00
highlighted: ( down || isSelected || additionalOptionsOpened ) && ! menuOpen
2020-11-15 01:50:12 +03:00
openMenuOnPressAndHold: ! messageListItem . precalculatedValues . pageIsSelecting
2020-12-15 21:15:12 +03:00
signal replyToMessage ( )
signal editMessage ( )
2021-12-05 04:25:24 +03:00
signal forwardMessage ( )
function deleteMessage ( ) {
var chatId = page . chatInformation . id
var messageId = myMessage . id
Remorse . itemAction ( messageListItem , qsTr ( "Message deleted" ) , function ( ) {
tdLibWrapper . deleteMessages ( chatId , [ messageId ] ) ;
} )
}
function copyMessageToClipboard ( ) {
Clipboard . text = Functions . getMessageText ( myMessage , true , userInformation . id , true )
}
2020-12-15 21:15:12 +03:00
2021-12-18 03:38:52 +03:00
function openContextMenu ( ) {
messageOptionsDrawer . open = false
if ( menu ) {
openMenu ( )
} else {
contextMenuLoader . active = true
}
}
2020-11-15 01:50:12 +03:00
onClicked: {
if ( messageListItem . precalculatedValues . pageIsSelecting ) {
page . toggleMessageSelection ( myMessage ) ;
2020-12-04 06:12:00 +03:00
} else {
2021-03-27 02:17:49 +03:00
if ( messageOptionsDrawer . sourceItem !== messageListItem ) {
messageOptionsDrawer . open = false
}
2020-12-04 06:12:00 +03:00
// Allow extra context to react to click
var extraContent = extraContentLoader . item
2021-02-03 13:47:03 +03:00
if ( extraContent && extraContentLoader . contains ( mapToItem ( extraContentLoader , mouse . x , mouse . y ) ) ) {
2020-12-04 06:12:00 +03:00
extraContent . clicked ( )
2020-12-24 06:42:41 +03:00
} else if ( webPagePreviewLoader . item ) {
webPagePreviewLoader . item . clicked ( )
2020-12-04 06:12:00 +03:00
}
2020-11-15 01:50:12 +03:00
}
}
2020-11-07 22:58:23 +03:00
onPressAndHold: {
2021-12-18 03:38:52 +03:00
if ( openMenuOnPressAndHold ) {
openContextMenu ( )
2020-11-15 01:50:12 +03:00
} else {
2021-12-18 03:38:52 +03:00
page . selectedMessages = [ ]
page . state = ""
2020-11-15 01:50:12 +03:00
}
2020-11-07 22:58:23 +03:00
}
2021-02-14 13:51:26 +03:00
onMenuOpenChanged: {
// When opening/closing the context menu, we no longer scroll automatically
chatView . manuallyScrolledToBottom = false ;
}
2021-02-14 23:57:48 +03:00
Connections {
2021-02-21 02:26:39 +03:00
target: additionalOptionsOpened ? messageOptionsDrawer : null
onOpenChanged: {
if ( ! messageOptionsDrawer . open ) {
additionalOptionsOpened = false
}
2021-02-14 23:57:48 +03:00
}
}
2020-11-07 22:58:23 +03:00
Loader {
id: contextMenuLoader
active: false
asynchronous: true
onStatusChanged: {
if ( status === Loader . Ready ) {
messageListItem . menu = item ;
messageListItem . openMenu ( ) ;
2020-11-05 16:05:33 +03:00
}
}
2020-11-07 22:58:23 +03:00
sourceComponent: Component {
ContextMenu {
MenuItem {
2021-12-05 04:25:24 +03:00
visible: canReplyToMessage
onClicked: replyToMessage ( )
2020-11-07 22:58:23 +03:00
text: qsTr ( "Reply to Message" )
}
MenuItem {
2021-12-06 00:06:05 +03:00
visible: typeof myMessage . can_be_edited !== "undefined" && myMessage . can_be_edited
2021-12-05 04:25:24 +03:00
onClicked: editMessage ( )
2020-12-15 21:15:12 +03:00
text: qsTr ( "Edit Message" )
2020-11-07 22:58:23 +03:00
}
MenuItem {
2021-12-05 04:25:24 +03:00
onClicked: page . toggleMessageSelection ( myMessage )
2021-02-14 23:57:48 +03:00
text: qsTr ( "Select Message" )
2020-11-07 22:58:23 +03:00
}
2020-11-15 01:50:12 +03:00
MenuItem {
2021-12-05 04:25:24 +03:00
visible: showCopyMessageToClipboardMenuItem
onClicked: copyMessageToClipboard ( )
text: qsTr ( "Copy Message to Clipboard" )
}
MenuItem {
visible: showForwardMessageMenuItem
onClicked: forwardMessage ( )
text: qsTr ( "Forward Message" )
}
MenuItem {
visible: canDeleteMessage && haveSpaceForDeleteMessageMenuItem
onClicked: deleteMessage ( )
text: qsTr ( "Delete Message" )
}
MenuItem {
visible: ( numberOfExtraOptionsOtherThanDeleteMessage > 0 ) ||
( deleteMessageIsOnlyExtraOption && ! haveSpaceForDeleteMessageMenuItem )
2020-11-15 01:50:12 +03:00
onClicked: {
2021-02-14 23:57:48 +03:00
messageOptionsDrawer . myMessage = myMessage ;
messageOptionsDrawer . userInformation = userInformation ;
2021-02-15 23:20:38 +03:00
messageOptionsDrawer . sourceItem = messageListItem
2021-12-05 04:25:24 +03:00
messageOptionsDrawer . additionalItemsModel = additionalItemsModel
messageOptionsDrawer . showCopyMessageToClipboardMenuItem = ! showCopyMessageToClipboardMenuItem
messageOptionsDrawer . showForwardMessageMenuItem = ! showForwardMessageMenuItem
messageOptionsDrawer . showDeleteMessageMenuItem = canDeleteMessage && ! haveSpaceForDeleteMessageMenuItem
2021-02-16 23:36:29 +03:00
messageListItem . additionalOptionsOpened = true ;
2021-02-14 23:57:48 +03:00
messageOptionsDrawer . open = true ;
2020-11-15 01:50:12 +03:00
}
2021-02-14 23:57:48 +03:00
text: qsTr ( "More Options..." )
2020-11-15 01:50:12 +03:00
}
2020-11-05 16:05:33 +03:00
}
}
}
Connections {
target: chatModel
2020-11-16 01:05:22 +03:00
onMessagesReceived: {
2021-12-06 00:06:05 +03:00
messageBackground . isUnread = index > chatModel . getLastReadMessageIndex ( ) && myMessage [ '@type' ] !== "sponsoredMessage" ;
2020-11-16 01:05:22 +03:00
}
onMessagesIncrementalUpdate: {
2021-12-06 00:06:05 +03:00
messageBackground . isUnread = index > chatModel . getLastReadMessageIndex ( ) && myMessage [ '@type' ] !== "sponsoredMessage" ;
2020-11-05 16:05:33 +03:00
}
onNewMessageReceived: {
2021-12-06 00:06:05 +03:00
messageBackground . isUnread = index > chatModel . getLastReadMessageIndex ( ) && myMessage [ '@type' ] !== "sponsoredMessage" ;
2020-11-16 01:05:22 +03:00
}
onUnreadCountUpdated: {
2021-12-06 00:06:05 +03:00
messageBackground . isUnread = index > chatModel . getLastReadMessageIndex ( ) && myMessage [ '@type' ] !== "sponsoredMessage" ;
2020-11-05 16:05:33 +03:00
}
onLastReadSentMessageUpdated: {
2020-11-20 23:58:26 +03:00
Debug . log ( "[ChatModel] Messages in this chat were read, new last read: " , lastReadSentIndex , ", updating description for index " , index , ", status: " , ( index <= lastReadSentIndex ) ) ;
2020-11-07 22:58:23 +03:00
messageDateText . text = getMessageStatusText ( myMessage , index , lastReadSentIndex , messageDateText . useElapsed ) ;
2020-11-05 16:05:33 +03:00
}
}
Connections {
target: tdLibWrapper
onReceivedMessage: {
2020-12-30 19:11:01 +03:00
if ( messageId === myMessage . reply_to_message_id ) {
2020-11-07 22:58:23 +03:00
messageInReplyToLoader . inReplyToMessage = message ;
2020-11-05 16:05:33 +03:00
}
}
2020-12-25 17:33:53 +03:00
onMessageNotFound: {
if ( messageId === myMessage . reply_to_message_id ) {
2021-02-10 00:35:19 +03:00
messageInReplyToLoader . inReplyToMessageDeleted = true ;
2020-12-25 17:33:53 +03:00
}
}
2020-11-05 16:05:33 +03:00
}
Component.onCompleted: {
delegateComponentLoadingTimer . start ( ) ;
2020-11-07 22:58:23 +03:00
if ( myMessage . reply_to_message_id !== 0 ) {
tdLibWrapper . getMessage ( page . chatInformation . id , myMessage . reply_to_message_id ) ;
}
2020-11-05 16:05:33 +03:00
}
2021-01-08 05:14:31 +03:00
onMyMessageChanged: {
2021-01-19 02:02:37 +03:00
Debug . log ( "[ChatModel] This message was updated, index" , messageIndex , ", updating content..." ) ;
messageDateText . text = getMessageStatusText ( myMessage , messageIndex , chatView . lastReadSentIndex , messageDateText . useElapsed ) ;
messageText . text = Emoji . emojify ( Functions . getMessageText ( myMessage , false , page . myUserId , false ) , Theme . fontSizeSmall ) ;
2021-01-08 05:14:31 +03:00
if ( webPagePreviewLoader . item ) {
2021-01-19 02:02:37 +03:00
webPagePreviewLoader . item . webPageData = myMessage . content . web_page ;
2021-01-08 05:14:31 +03:00
}
}
2020-11-05 16:05:33 +03:00
Timer {
id: delegateComponentLoadingTimer
interval: 500
repeat: false
running: false
onTriggered: {
2021-01-15 12:55:34 +03:00
if ( messageListItem . hasContentComponent ) {
var type = myMessage . content [ "@type" ] ;
extraContentLoader . setSource (
"../components/messageContent/" + type . charAt ( 0 ) . toUpperCase ( ) + type . substring ( 1 ) + ".qml" ,
{
messageListItem: messageListItem
} )
} else {
if ( typeof myMessage . content . web_page !== "undefined" ) { // only in messageText
webPagePreviewLoader . active = true ;
2020-11-05 16:05:33 +03:00
}
}
}
}
Row {
id: messageTextRow
spacing: Theme . paddingSmall
2020-11-07 22:58:23 +03:00
width: precalculatedValues . entryWidth
anchors.centerIn: parent
2020-11-05 16:05:33 +03:00
Loader {
id: profileThumbnailLoader
2020-11-07 22:58:23 +03:00
active: precalculatedValues . showUserInfo
2020-11-05 16:05:33 +03:00
asynchronous: true
2020-11-07 22:58:23 +03:00
width: precalculatedValues . profileThumbnailDimensions
height: width
2020-11-05 16:05:33 +03:00
anchors.bottom: parent . bottom
anchors.bottomMargin: Theme . paddingSmall
sourceComponent: Component {
ProfileThumbnail {
id: messagePictureThumbnail
2020-12-25 15:50:13 +03:00
photoData: messageListItem . isAnonymous ? ( ( typeof page . chatInformation . photo !== "undefined" ) ? page.chatInformation.photo.small : { } ) : ( ( typeof messageListItem . userInformation . profile_photo !== "undefined" ) ? messageListItem.userInformation.profile_photo.small : ( { } ) )
2020-11-05 16:05:33 +03:00
replacementStringHint: userText . text
2020-11-07 22:58:23 +03:00
width: Theme . itemSizeSmall
height: Theme . itemSizeSmall
visible: precalculatedValues . showUserInfo
2020-11-05 16:05:33 +03:00
MouseArea {
anchors.fill: parent
2020-12-25 15:50:13 +03:00
enabled: ! ( messageListItem . precalculatedValues . pageIsSelecting || messageListItem . isAnonymous )
2020-11-05 16:05:33 +03:00
onClicked: {
2021-01-10 04:06:41 +03:00
tdLibWrapper . createPrivateChat ( messageListItem . userInformation . id , "openDirectly" ) ;
2020-11-05 16:05:33 +03:00
}
}
}
}
}
Item {
id: messageTextItem
2020-11-07 22:58:23 +03:00
width: precalculatedValues . textItemWidth
2020-11-05 16:05:33 +03:00
height: messageBackground . height
Rectangle {
id: messageBackground
2020-11-16 01:05:22 +03:00
2020-11-05 16:05:33 +03:00
anchors {
left: parent . left
2020-11-07 22:58:23 +03:00
leftMargin: messageListItem . isOwnMessage ? precalculatedValues.pageMarginDouble : 0
2020-11-05 16:05:33 +03:00
verticalCenter: parent . verticalCenter
}
2020-11-16 17:12:18 +03:00
height: messageTextColumn . height + precalculatedValues . paddingMediumDouble
2020-11-07 22:58:23 +03:00
width: precalculatedValues . backgroundWidth
2021-12-06 00:06:05 +03:00
property bool isUnread: index > chatModel . getLastReadMessageIndex ( ) && myMessage [ '@type' ] !== "sponsoredMessage"
2020-12-30 15:49:57 +03:00
color: Theme . colorScheme === Theme . LightOnDark ? ( isUnread ? Theme.secondaryHighlightColor : Theme . secondaryColor ) : ( isUnread ? Theme.backgroundGlowColor : Theme . overlayBackgroundColor )
2020-11-05 16:05:33 +03:00
radius: parent . width / 50
2020-11-07 22:58:23 +03:00
opacity: isUnread ? 0.5 : 0.2
2021-12-08 21:48:44 +03:00
visible: appSettings . showStickersAsImages || ( myMessage . content [ '@type' ] !== "messageSticker" && myMessage . content [ '@type' ] !== "messageAnimatedEmoji" )
2020-11-05 16:05:33 +03:00
Behavior on color { ColorAnimation { duration: 200 } }
Behavior on opacity { FadeAnimation { } }
}
Column {
id: messageTextColumn
spacing: Theme . paddingSmall
2020-11-07 22:58:23 +03:00
width: precalculatedValues . textColumnWidth
2020-11-05 16:05:33 +03:00
anchors.centerIn: messageBackground
2020-11-22 02:39:49 +03:00
Label {
2020-11-05 16:05:33 +03:00
id: userText
width: parent . width
2021-12-06 00:06:05 +03:00
text: messageListItem . isOwnMessage ? qsTr ( "You" ) : Emoji . emojify ( myMessage [ '@type' ] === "sponsoredMessage" ? tdLibWrapper . getChat ( myMessage . sponsor_chat_id ) . title : ( messageListItem . isAnonymous ? page.chatInformation.title : Functions . getUserName ( messageListItem . userInformation ) ) , font . pixelSize )
2020-11-05 16:05:33 +03:00
font.pixelSize: Theme . fontSizeExtraSmall
font.weight: Font . ExtraBold
2020-11-07 22:58:23 +03:00
color: messageListItem . textColor
2020-11-05 16:05:33 +03:00
maximumLineCount: 1
2020-11-22 02:39:49 +03:00
truncationMode: TruncationMode . Fade
2020-11-05 16:05:33 +03:00
textFormat: Text . StyledText
2020-11-07 22:58:23 +03:00
horizontalAlignment: messageListItem . textAlign
2021-12-06 00:06:05 +03:00
visible: precalculatedValues . showUserInfo || myMessage [ '@type' ] === "sponsoredMessage"
2020-11-05 16:05:33 +03:00
MouseArea {
anchors.fill: parent
2020-12-25 15:50:13 +03:00
enabled: ! ( messageListItem . precalculatedValues . pageIsSelecting || messageListItem . isAnonymous )
2020-11-05 16:05:33 +03:00
onClicked: {
2021-01-10 04:06:41 +03:00
tdLibWrapper . createPrivateChat ( messageListItem . userInformation . id , "openDirectly" ) ;
2020-11-05 16:05:33 +03:00
}
}
}
2021-01-10 04:06:41 +03:00
MessageViaLabel {
message: myMessage
}
2020-11-07 22:58:23 +03:00
Loader {
id: messageInReplyToLoader
2021-12-06 00:06:05 +03:00
active: typeof myMessage . reply_to_message_id !== "undefined" && myMessage . reply_to_message_id !== 0
2020-11-07 22:58:23 +03:00
width: parent . width
// text height ~= 1,28*font.pixelSize
height: active ? precalculatedValues.messageInReplyToHeight : 0
property var inReplyToMessage ;
2021-02-10 00:35:19 +03:00
property bool inReplyToMessageDeleted: false ;
2020-11-07 22:58:23 +03:00
sourceComponent: Component {
2020-11-17 22:25:57 +03:00
Item {
width: messageInReplyToRow . width
height: messageInReplyToRow . height
InReplyToRow {
id: messageInReplyToRow
myUserId: page . myUserId
2021-12-18 03:38:52 +03:00
layer.enabled: messageInReplyToMouseArea . pressed && ! messageListItem . highlighted && ! messageListItem . menuOpen
layer.effect: PressEffect { source: messageInReplyToRow }
2020-11-17 22:25:57 +03:00
inReplyToMessage: messageInReplyToLoader . inReplyToMessage
2021-02-10 00:35:19 +03:00
inReplyToMessageDeleted: messageInReplyToLoader . inReplyToMessageDeleted
2020-11-17 22:25:57 +03:00
}
MouseArea {
2021-12-18 03:38:52 +03:00
id: messageInReplyToMouseArea
2020-11-17 22:25:57 +03:00
anchors.fill: parent
onClicked: {
2021-12-18 03:38:52 +03:00
if ( precalculatedValues . pageIsSelecting ) {
page . toggleMessageSelection ( myMessage )
} else {
messageOptionsDrawer . open = false
messageOverlayLoader . overlayMessage = messageInReplyToRow . inReplyToMessage
messageOverlayLoader . active = true
}
}
onPressAndHold: {
if ( openMenuOnPressAndHold ) {
openContextMenu ( )
}
2020-11-17 22:25:57 +03:00
}
}
2020-11-07 22:58:23 +03:00
}
}
2020-11-05 16:05:33 +03:00
}
Loader {
id: forwardedInformationLoader
2020-11-07 22:58:23 +03:00
active: typeof myMessage . forward_info !== "undefined"
2020-11-05 16:05:33 +03:00
asynchronous: true
width: parent . width
2020-11-07 22:58:23 +03:00
height: active ? ( item ? item.height : Theme . itemSizeExtraSmall ) : 0
2020-11-05 16:05:33 +03:00
sourceComponent: Component {
Row {
id: forwardedMessageInformationRow
spacing: Theme . paddingSmall
width: parent . width
Component.onCompleted: {
2020-11-07 22:58:23 +03:00
if ( myMessage . forward_info . origin [ "@type" ] === "messageForwardOriginChannel" ) {
var otherChatInformation = tdLibWrapper . getChat ( myMessage . forward_info . origin . chat_id ) ;
2020-11-15 01:50:12 +03:00
forwardedThumbnail . photoData = ( typeof otherChatInformation . photo !== "undefined" ) ? otherChatInformation.photo.small : { } ;
2020-11-05 16:05:33 +03:00
forwardedChannelText . text = Emoji . emojify ( otherChatInformation . title , Theme . fontSizeExtraSmall ) ;
2020-11-07 22:58:23 +03:00
} else if ( myMessage . forward_info . origin [ "@type" ] === "messageForwardOriginUser" ) {
2020-12-08 00:13:51 +03:00
var otherUserInformation = tdLibWrapper . getUserInformation ( myMessage . forward_info . origin . sender_user_id ) ;
2020-11-15 01:50:12 +03:00
forwardedThumbnail . photoData = ( typeof otherUserInformation . profile_photo !== "undefined" ) ? otherUserInformation.profile_photo.small : { } ;
2020-11-05 16:05:33 +03:00
forwardedChannelText . text = Emoji . emojify ( Functions . getUserName ( otherUserInformation ) , Theme . fontSizeExtraSmall ) ;
} else {
2020-11-14 22:02:34 +03:00
forwardedChannelText . text = Emoji . emojify ( myMessage . forward_info . origin . sender_name , Theme . fontSizeExtraSmall ) ;
forwardedThumbnail . photoData = { } ;
2020-11-05 16:05:33 +03:00
}
}
ProfileThumbnail {
id: forwardedThumbnail
replacementStringHint: forwardedChannelText . text
width: Theme . itemSizeExtraSmall
height: Theme . itemSizeExtraSmall
}
Column {
spacing: Theme . paddingSmall
2020-11-14 22:02:34 +03:00
width: parent . width - forwardedThumbnail . width - Theme . paddingSmall
2020-11-22 02:39:49 +03:00
Label {
2020-11-05 16:05:33 +03:00
font.pixelSize: Theme . fontSizeExtraSmall
width: parent . width
font.italic: true
2020-11-22 02:39:49 +03:00
truncationMode: TruncationMode . Fade
2020-11-05 16:05:33 +03:00
textFormat: Text . StyledText
text: qsTr ( "Forwarded Message" )
}
2020-11-22 02:39:49 +03:00
Label {
2020-11-05 16:05:33 +03:00
id: forwardedChannelText
font.pixelSize: Theme . fontSizeExtraSmall
color: Theme . primaryColor
width: parent . width
font.bold: true
2020-11-22 02:39:49 +03:00
truncationMode: TruncationMode . Fade
2020-11-05 16:05:33 +03:00
textFormat: Text . StyledText
text: Emoji . emojify ( forwardedMessageInformationRow . otherChatInformation . title , font . pixelSize )
}
}
}
}
}
Text {
id: messageText
width: parent . width
2021-01-19 02:02:37 +03:00
text: Emoji . emojify ( Functions . getMessageText ( myMessage , false , page . myUserId , false ) , Theme . fontSizeMedium )
2020-11-05 16:05:33 +03:00
font.pixelSize: Theme . fontSizeSmall
2020-11-07 22:58:23 +03:00
color: messageListItem . textColor
2020-11-05 16:05:33 +03:00
wrapMode: Text . Wrap
textFormat: Text . StyledText
onLinkActivated: {
2020-12-27 02:01:59 +03:00
var chatCommand = Functions . handleLink ( link ) ;
if ( chatCommand ) {
tdLibWrapper . sendTextMessage ( chatInformation . id , chatCommand ) ;
}
2020-11-05 16:05:33 +03:00
}
2020-11-07 22:58:23 +03:00
horizontalAlignment: messageListItem . textAlign
2020-11-05 16:05:33 +03:00
linkColor: Theme . highlightColor
visible: ( text !== "" )
}
2021-12-06 00:06:05 +03:00
Loader {
id: sponsoredMessageButtonLoader
active: myMessage [ '@type' ] === "sponsoredMessage"
asynchronous: true
width: parent . width
height: ( status === Loader . Ready ) ? item.implicitHeight : myMessage [ '@type' ] === "sponsoredMessage" ? Theme.itemSizeMedium : 0
sourceComponent: Component {
SponsoredMessage {
sponsoredMessageData: myMessage
width: parent . width
}
}
}
2020-11-05 16:05:33 +03:00
Loader {
id: webPagePreviewLoader
active: false
asynchronous: true
width: parent . width
2020-12-24 06:42:41 +03:00
height: ( status === Loader . Ready ) ? item.implicitHeight : myMessage . content . web_page ? precalculatedValues.webPagePreviewHeight : 0
2020-11-05 16:05:33 +03:00
sourceComponent: Component {
WebPagePreview {
2020-11-07 22:58:23 +03:00
webPageData: myMessage . content . web_page
2020-11-05 16:05:33 +03:00
width: parent . width
2020-12-05 00:47:03 +03:00
highlighted: messageListItem . highlighted
2020-11-05 16:05:33 +03:00
}
}
}
2020-12-04 22:29:31 +03:00
2020-11-05 16:05:33 +03:00
Loader {
id: extraContentLoader
width: parent . width
asynchronous: true
2021-01-15 12:55:34 +03:00
height: item ? item.height : ( messageListItem . hasContentComponent ? chatView . getContentComponentHeight ( model . content_type , myMessage . content , width ) : 0 )
2020-11-05 16:05:33 +03:00
}
2020-12-04 22:29:31 +03:00
Binding {
target: extraContentLoader . item
when: extraContentLoader . item && ( "highlighted" in extraContentLoader . item ) && ( typeof extraContentLoader . item . highlighted === "boolean" )
property: "highlighted"
value: messageListItem . highlighted
}
2020-12-27 02:01:59 +03:00
Loader {
id: replyMarkupLoader
width: parent . width
height: active ? ( myMessage . reply_markup . rows . length * ( Theme . itemSizeSmall + Theme . paddingSmall ) - Theme . paddingSmall ) : 0
asynchronous: true
active: ! ! myMessage . reply_markup && myMessage . reply_markup . rows
source: Qt . resolvedUrl ( "ReplyMarkupButtons.qml" )
}
2020-11-05 16:05:33 +03:00
Timer {
id: messageDateUpdater
interval: 60000
running: true
repeat: true
onTriggered: {
2020-11-07 22:58:23 +03:00
messageDateText . text = getMessageStatusText ( myMessage , index , chatView . lastReadSentIndex , messageDateText . useElapsed ) ;
2020-11-05 16:05:33 +03:00
}
}
Text {
width: parent . width
property bool useElapsed: true
id: messageDateText
font.pixelSize: Theme . fontSizeTiny
color: messageListItem . isOwnMessage ? Theme.secondaryHighlightColor : Theme . secondaryColor
2020-11-07 22:58:23 +03:00
horizontalAlignment: messageListItem . textAlign
text: getMessageStatusText ( myMessage , index , chatView . lastReadSentIndex , messageDateText . useElapsed )
2021-01-19 02:12:59 +03:00
rightPadding: interactionLoader . active ? interactionLoader.width : 0
2020-11-05 16:05:33 +03:00
MouseArea {
anchors.fill: parent
2020-11-15 01:50:12 +03:00
enabled: ! messageListItem . precalculatedValues . pageIsSelecting
2020-11-05 16:05:33 +03:00
onClicked: {
messageDateText . useElapsed = ! messageDateText . useElapsed ;
2020-11-07 22:58:23 +03:00
messageDateText . text = getMessageStatusText ( myMessage , index , chatView . lastReadSentIndex , messageDateText . useElapsed ) ;
2020-11-05 16:05:33 +03:00
}
}
2021-01-19 02:12:59 +03:00
Loader {
id: interactionLoader
height: parent . height
anchors.right: parent . right
asynchronous: true
2021-01-31 23:08:39 +03:00
active: chatPage . isChannel && messageViewCount
2021-01-19 02:12:59 +03:00
sourceComponent: Component {
Label {
2021-01-31 23:08:39 +03:00
text: Functions . getShortenedCount ( messageViewCount )
2021-01-19 02:12:59 +03:00
leftPadding: Theme . iconSizeSmall
font.pixelSize: Theme . fontSizeTiny
color: Theme . secondaryColor
Icon {
anchors.verticalCenter: parent . verticalCenter
width: Theme . iconSizeExtraSmall
height: Theme . iconSizeExtraSmall
opacity: 0.6
source: "../../images/icon-s-eye.svg"
sourceSize {
width: Theme . iconSizeExtraSmall
height: Theme . iconSizeExtraSmall
}
}
}
}
}
2020-11-05 16:05:33 +03:00
}
}
}
}
}