From 1fa719272895e78efc3c1b3563ed0eaa3245629b Mon Sep 17 00:00:00 2001 From: John Gibbon Date: Fri, 30 Oct 2020 20:36:32 +0100 Subject: [PATCH] Reduce ChatPage.qml jit compile time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First of all: Take all measurements I mention with a grain of salt – all of them are rough and not necessarily measured more than a few times. All times were measured on an Xperia X run via SDK. Visiting a chat page can take a long time, especially before the qml is cached by the engine. When opening it for the first time after application launch, it sometimes takes >1000ms from onClicked (OverviewPage) to Component.OnCompleted (Chatpage). Subsequent activations take roughly 470-480ms. With these changes, I was able to reduce these times to ~450ms for the first, ~100ms for subsequent activations of the ChatPage on my test device. Things changed: - The components for displaying extra content to a message are (mostly) gone and replaced by a single Loader. This Loader does not use sourceComponent to trade the initial compilation boost for a neglegible bit of runtime penalty. - Connections were consolidated - I was surprised how costly the inclusion of the RemorseItem was (compiling ~75ms, initializing up to ~20ms for every delegate). So I traded a bit for a compromise. deleteMessageRemorseItem is now defined on the appWindow level, where it gets a bit mitigated by the animations at application start. Also, only one deletion at a time is now possible. We can easily revert this change, but I thought it worthwhile despite its drawbacks. - profileThumbnailComponent is now defined directly as sourceComponent, removing the need for its id. Probably didn't do anything. - InReplyToRow had width: parent.width, so I removed horizontalCenter. Also probably didn't change compilation time at all. - Another compromise I was willing to take – your opinion may differ: The PickerPages took ages (~200ms) to just parse/compile inside those Components, so I replaced them with the "string notation" of pageStack.push. Drawback: The first time a picker gets activated, you'll see how slow it is. Subsequent activations aren't that bad – also for the other pickers. --- qml/components/AudioPreview.qml | 9 +- qml/components/DocumentPreview.qml | 5 +- qml/components/ImagePreview.qml | 7 +- qml/components/LocationPreview.qml | 11 +- qml/components/PollPreview.qml | 23 +- qml/components/StickerPreview.qml | 6 +- qml/components/VideoPreview.qml | 9 +- qml/harbour-fernschreiber.qml | 4 + qml/pages/ChatPage.qml | 365 +++++++++-------------------- 9 files changed, 159 insertions(+), 280 deletions(-) diff --git a/qml/components/AudioPreview.qml b/qml/components/AudioPreview.qml index 3b37e55..0b59911 100644 --- a/qml/components/AudioPreview.qml +++ b/qml/components/AudioPreview.qml @@ -24,15 +24,18 @@ import "../js/functions.js" as Functions Item { id: audioMessageComponent - property variant audioData; + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + + property variant audioData: ( rawMessage.content['@type'] === "messageVoiceNote" ) ? rawMessage.content.voice_note : ( ( rawMessage.content['@type'] === "messageAudio" ) ? rawMessage.content.audio : ""); property string audioUrl; property int previewFileId; property int audioFileId; - property bool onScreen; + property bool onScreen: messageListItem.page.status === PageStatus.Active property string audioType : "voiceNote"; width: parent.width - height: parent.height + height: width / 2 function getTimeString(rawSeconds) { var minutes = Math.floor( rawSeconds / 60 ); diff --git a/qml/components/DocumentPreview.qml b/qml/components/DocumentPreview.qml index 9f46a09..2b656a0 100644 --- a/qml/components/DocumentPreview.qml +++ b/qml/components/DocumentPreview.qml @@ -26,7 +26,10 @@ Item { width: parent.width height: Theme.itemSizeLarge - property variant documentData; + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + + property variant documentData: rawMessage.content.document property bool openRequested: false; Component.onCompleted: { diff --git a/qml/components/ImagePreview.qml b/qml/components/ImagePreview.qml index ea8571d..8156762 100644 --- a/qml/components/ImagePreview.qml +++ b/qml/components/ImagePreview.qml @@ -24,9 +24,14 @@ Item { id: imagePreviewItem - property variant photoData; + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + property variant photoData: rawMessage.content.photo; property variant pictureFileInformation; + width: parent.width + height: width * 2 / 3 + Component.onCompleted: { updatePicture(); } diff --git a/qml/components/LocationPreview.qml b/qml/components/LocationPreview.qml index 6964340..ecffa23 100644 --- a/qml/components/LocationPreview.qml +++ b/qml/components/LocationPreview.qml @@ -23,9 +23,16 @@ import Sailfish.Silica 1.0 Item { id: imagePreviewItem - property variant locationData; - property int chatId; + + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + + property variant locationData : ( rawMessage.content['@type'] === "messageLocation" ) ? rawMessage.content.location : ( ( rawMessage.content['@type'] === "messageVenue" ) ? rawMessage.content.venue.location : "" ) + + property string chatId: messageListItem.page.chatInformation.id property variant pictureFileInformation; + width: parent.width + height: width / 2 Component.onCompleted: { updatePicture(); diff --git a/qml/components/PollPreview.qml b/qml/components/PollPreview.qml index c4261e2..00d3101 100644 --- a/qml/components/PollPreview.qml +++ b/qml/components/PollPreview.qml @@ -27,13 +27,16 @@ import "../js/twemoji.js" as Emoji Item { id: pollMessageComponent - property string chatId - property var message:({}) - property bool isOwnMessage - property string messageId: message.id - property bool canEdit: message.can_be_edited - property var pollData: message.content.poll + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + property string chatId: messageListItem.page.chatInformation.id + + property bool isOwnMessage: messageListItem.isOwnMessage + + property string messageId: rawMessage.id + property bool canEdit: rawMessage.can_be_edited + property var pollData: rawMessage.content.poll property var chosenPollData:({}) property var chosenIndexes: [] property bool hasAnswered: { @@ -43,7 +46,7 @@ Item { } property bool canAnswer: !hasAnswered && !pollData.is_closed property bool isQuiz: pollData.type['@type'] === "pollTypeQuiz" - property Item messageItem + width: parent.width height: pollColumn.height opacity: 0 Behavior on opacity { FadeAnimation {} } @@ -286,9 +289,9 @@ Item { Component.onCompleted: { opacity = 1; - if(messageItem && messageItem.menu ) { // workaround to add menu entries - closePollMenuItemComponent.createObject(messageItem.menu._contentColumn); - resetAnswerMenuItemComponent.createObject(messageItem.menu._contentColumn); + if(messageListItem && messageListItem.menu ) { // workaround to add menu entries + closePollMenuItemComponent.createObject(messageListItem.menu._contentColumn); + resetAnswerMenuItemComponent.createObject(messageListItem.menu._contentColumn); } } } diff --git a/qml/components/StickerPreview.qml b/qml/components/StickerPreview.qml index 070f668..9049671 100644 --- a/qml/components/StickerPreview.qml +++ b/qml/components/StickerPreview.qml @@ -20,7 +20,11 @@ import QtQuick 2.5 import Sailfish.Silica 1.0 Item { - property variant stickerData; + + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + + property variant stickerData: rawMessage.content.sticker; property int usedFileId; width: stickerData.width diff --git a/qml/components/VideoPreview.qml b/qml/components/VideoPreview.qml index 6646d8e..a7fe357 100644 --- a/qml/components/VideoPreview.qml +++ b/qml/components/VideoPreview.qml @@ -24,17 +24,20 @@ import "../js/functions.js" as Functions Item { id: videoMessageComponent - property variant videoData; + property ListItem messageListItem + property variant rawMessage: messageListItem.myMessage + + property variant videoData: ( rawMessage.content['@type'] === "messageVideo" ) ? rawMessage.content.video : ( ( rawMessage.content['@type'] === "messageAnimation" ) ? rawMessage.content.animation : "") property string videoUrl; property int previewFileId; property int videoFileId; property bool fullscreen : false; - property bool onScreen; + property bool onScreen: messageListItem.page.status === PageStatus.Active; property string videoType : "video"; property bool playRequested: false; width: parent.width - height: parent.height + height: Functions.getVideoHeight(width, videoData) Timer { id: screensaverTimer diff --git a/qml/harbour-fernschreiber.qml b/qml/harbour-fernschreiber.qml index 8c756cd..42bdf31 100644 --- a/qml/harbour-fernschreiber.qml +++ b/qml/harbour-fernschreiber.qml @@ -28,6 +28,10 @@ ApplicationWindow cover: Qt.resolvedUrl("pages/CoverPage.qml") allowedOrientations: defaultAllowedOrientations + RemorseItem { + id: deleteMessageRemorseItem + } + Connections { target: dBusAdaptor onPleaseOpenMessage: { diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index ce8ff10..7ebb21f 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -225,8 +225,6 @@ Page { chatPage.isInitialized = true; } break; -// case PageStatus.Deactivating: -// tdLibWrapper.closeChat(chatInformation.id); } } @@ -314,6 +312,10 @@ Page { chatView.lastReadSentIndex = lastReadSentIndex; chatViewCooldownTimer.start(); } + onNotificationSettingsUpdated: { + chatInformation = chatModel.getChatInformation(); + muteChatMenuItem.text = chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat"); + } } Timer { @@ -348,9 +350,9 @@ Page { SilicaFlickable { id: chatContainer - contentHeight: parent.height - contentWidth: parent.width anchors.fill: parent + contentHeight: height + contentWidth: width PullDownMenu { visible: chatInformation.id !== chatPage.myUserId && !stickerPickerLoader.active @@ -369,13 +371,6 @@ Page { } } - Connections { - target: chatModel - onNotificationSettingsUpdated: { - chatInformation = chatModel.getChatInformation(); - muteChatMenuItem.text = chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat"); - } - } BackgroundItem { id: headerMouseArea height: headerRow.height @@ -463,16 +458,6 @@ Page { previousHeight = height; } - Timer { - id: chatViewLoadingTimer - interval: 100 - repeat: false - running: false - onTriggered: { - chatPage.loading = false; - } - } - Timer { id: chatViewCooldownTimer interval: 2000 @@ -484,6 +469,7 @@ Page { } } + SilicaListView { id: chatView @@ -519,24 +505,28 @@ Page { } model: chatModel + property variant contentComponentNames: ({ + messageSticker: "StickerPreview", + messagePhoto: "ImagePreview", + messageVideo: "VideoPreview", + messageAnimation: "VideoPreview", + messageAudio: "AudioPreview", + messageVoiceNote: "AudioPreview", + messageDocument: "DocumentPreview", + messageLocation: "LocationPreview", + messageVenue: "LocationPreview", + messagePoll: "PollPreview" + }) delegate: ListItem { - id: messageListItem contentHeight: messageBackground.height + Theme.paddingMedium contentWidth: parent.width property variant myMessage: display property variant userInformation: tdLibWrapper.getUserInformation(display.sender_user_id) + property Page page: chatPage + property bool isOwnMessage: chatPage.myUserId === display.sender_user_id - property bool isForwarded: typeof display.forward_info !== "undefined" - property bool containsImage: display.content['@type'] === "messagePhoto" - property bool containsSticker: display.content['@type'] === "messageSticker" - property bool containsWebPage: typeof display.content.web_page !== "undefined" - property bool containsVideo: (( display.content['@type'] === "messageVideo" ) || ( display.content['@type'] === "messageAnimation" )); - property bool containsAudio: (( display.content['@type'] === "messageVoiceNote" ) || ( display.content['@type'] === "messageAudio" )); - property bool containsDocument: ( display.content['@type'] === "messageDocument" ) - property bool containsLocation: ( display.content['@type'] === "messageLocation" || ( display.content['@type'] === "messageVenue" )) - property bool containsPoll: display.content['@type'] === "messagePoll" menu: ContextMenu { MenuItem { @@ -556,6 +546,7 @@ Page { visible: display.can_be_edited } MenuItem { + enabled: !deleteMessageRemorseItem.pending onClicked: { deleteMessageRemorseItem.execute(messageListItem, qsTr("Deleting message"), function() { tdLibWrapper.deleteMessages(chatInformation.id, [ display.id ]); } ); } @@ -574,6 +565,32 @@ Page { messageBackground.color = index > ( chatView.count - chatInformation.unreadCount - 1 ) ? Theme.secondaryHighlightColor : Theme.secondaryColor; messageBackground.opacity = index > ( chatView.count - chatInformation.unreadCount - 1 ) ? 0.5 : 0.2; } + + onLastReadSentMessageUpdated: { + console.log("[ChatModel] Messages in this chat were read, new last read: " + lastReadSentIndex + ", updating description for index " + index + ", status: " + (index <= lastReadSentIndex)); + messageDateText.text = getMessageStatusText(display, index, lastReadSentIndex); + } + onMessageUpdated: { + if (index === modelIndex) { + console.log("[ChatModel] This message was updated, index " + index + ", updating content..."); + messageDateText.text = getMessageStatusText(display, index, chatView.lastReadSentIndex); + messageText.text = Emoji.emojify(Functions.getMessageText(display, false, messageListItem.isOwnMessage), messageText.font.pixelSize); + if(locationPreviewLoader.active && locationPreviewLoader.status === Loader.Ready) { + locationPreviewLoader.item.locationData = display.content.location; + locationPreviewLoader.item.updatePicture() + } + } + } + } + + Connections { + target: tdLibWrapper + onReceivedMessage: { + if (messageId === display.reply_to_message_id.toString()) { + messageInReplyToRow.inReplyToMessage = message; + messageInReplyToRow.visible = true; + } + } } Component.onCompleted: { @@ -587,22 +604,21 @@ Page { running: false onTriggered: { if (typeof display.content !== "undefined") { - webPagePreviewLoader.active = messageListItem.containsWebPage; - imagePreviewLoader.active = messageListItem.containsImage; - stickerPreviewLoader.active = messageListItem.containsSticker; - videoPreviewLoader.active = messageListItem.containsVideo; - audioPreviewLoader.active = messageListItem.containsAudio; - documentPreviewLoader.active = messageListItem.containsDocument; - locationPreviewLoader.active = messageListItem.containsLocation; - pollPreviewLoader.active = messageListItem.containsPoll; - forwardedInformationLoader.active = messageListItem.isForwarded; + if(chatView.contentComponentNames.hasOwnProperty(display.content['@type'])) { + extraContentLoader.setSource( + "../components/" +chatView.contentComponentNames[display.content['@type']] +".qml", + { + messageListItem: messageListItem + }) + } else { + if(typeof display.content.web_page !== "undefined") { // only in messageText + webPagePreviewLoader.active = true; + } + } } } } - RemorseItem { - id: deleteMessageRemorseItem - } Row { id: messageTextRow @@ -611,18 +627,6 @@ Page { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - Component { - id: profileThumbnailComponent - ProfileThumbnail { - id: messagePictureThumbnail - photoData: (typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : "" - replacementStringHint: userText.text - width: visible ? Theme.itemSizeSmall : 0 - height: visible ? Theme.itemSizeSmall : 0 - visible: ( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel - } - } - Loader { id: profileThumbnailLoader active: (( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel) @@ -631,7 +635,16 @@ Page { height: active ? Theme.itemSizeSmall : 0 anchors.bottom: parent.bottom anchors.bottomMargin: Theme.paddingSmall - sourceComponent: profileThumbnailComponent + sourceComponent: Component { + ProfileThumbnail { + id: messagePictureThumbnail + photoData: (typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : "" + replacementStringHint: userText.text + width: visible ? Theme.itemSizeSmall : 0 + height: visible ? Theme.itemSizeSmall : 0 + visible: ( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel + } + } } Item { @@ -654,7 +667,7 @@ Page { color: index > ( chatView.count - chatInformation.unread_count - 1 ) ? Theme.secondaryHighlightColor : Theme.secondaryColor radius: parent.width / 50 opacity: index > ( chatView.count - chatInformation.unread_count - 1 ) ? 0.5 : 0.2 - visible: appSettings.showStickersAsImages || !messageListItem.containsSticker + visible: appSettings.showStickersAsImages || display.content['@type'] !== "messageSticker" } Column { @@ -671,15 +684,6 @@ Page { } } - Connections { - target: tdLibWrapper - onReceivedMessage: { - if (messageId === display.reply_to_message_id.toString()) { - messageInReplyToRow.inReplyToMessage = message; - messageInReplyToRow.visible = true; - } - } - } Text { id: userText @@ -704,10 +708,10 @@ Page { Loader { id: forwardedInformationLoader - active: false + active: typeof display.forward_info !== "undefined" asynchronous: true width: parent.width - height: messageListItem.isForwarded ? ( item ? item.height : Theme.itemSizeExtraSmall ) : 0 +// height: active ? ( item ? item.height : Theme.itemSizeExtraSmall ) : 0 sourceComponent: Component { Row { id: forwardedMessageInformationRow @@ -817,128 +821,10 @@ Page { } } } - Loader { - id: imagePreviewLoader - active: false - asynchronous: true + id: extraContentLoader width: parent.width - height: messageListItem.containsImage ? (item ? item.height : (parent.width * 2 / 3)) : 0 - sourceComponent: Component { - id: imagePreviewComponent - ImagePreview { - id: messageImagePreview - photoData: messageListItem.containsImage ? display.content.photo : "" - width: parent.width - height: parent.width * 2 / 3 - } - } - } - - Loader - { - id: stickerPreviewLoader - active: false asynchronous: true - x: messageListItem.isOwnMessage ? (parent.width - width) : 0 - width: (appSettings.showStickersAsImages || !item) ? parent.width : item.width - height: messageListItem.containsSticker ? display.content.sticker.height : 0 - - sourceComponent: Component { - id: stickerPreviewComponent - StickerPreview { - id: messageStickerPreview - stickerData: messageListItem.containsSticker ? display.content.sticker : "" - } - } - } - - Loader { - id: videoPreviewLoader - active: false - asynchronous: true - width: parent.width - height: messageListItem.containsVideo ? Functions.getVideoHeight(width, ( display.content['@type'] === "messageVideo" ) ? display.content.video : display.content.animation) : 0 - sourceComponent: Component { - id: videoPreviewComponent - VideoPreview { - id: messageVideoPreview - videoData: ( display.content['@type'] === "messageVideo" ) ? display.content.video : ( ( display.content['@type'] === "messageAnimation" ) ? display.content.animation : "") - width: parent.width - height: Functions.getVideoHeight(width, ( display.content['@type'] === "messageVideo" ) ? display.content.video : display.content.animation) - onScreen: chatPage.status === PageStatus.Active - } - } - } - - Loader { - id: audioPreviewLoader - active: false - asynchronous: true - width: parent.width - height: messageListItem.containsAudio ? (parent.width / 2) : 0 - sourceComponent: Component { - id: audioPreviewComponent - AudioPreview { - id: messageAudioPreview - audioData: ( display.content['@type'] === "messageVoiceNote" ) ? display.content.voice_note : ( ( display.content['@type'] === "messageAudio" ) ? display.content.audio : "") - width: parent.width - height: parent.width / 2 - onScreen: chatPage.status === PageStatus.Active - } - } - } - - Loader { - id: documentPreviewLoader - active: false - asynchronous: true - width: parent.width - height: messageListItem.containsDocument ? (item ? item.height : Theme.itemSizeSmall) : 0 - sourceComponent: Component { - id: documentPreviewComponent - DocumentPreview { - id: messageDocumentPreview - documentData: messageListItem.containsDocument ? display.content.document : "" - } - } - } - - Loader { - id: locationPreviewLoader - active: false - asynchronous: true - width: parent.width - height: messageListItem.containsLocation ? (item ? item.height : (parent.width * 2 / 3)) : 0 - sourceComponent: Component { - id: locationPreviewComponent - LocationPreview { - id: messageLocationPreview - width: parent.width - height: parent.width * 2 / 3 - chatId: display.id - locationData: ( display.content['@type'] === "messageLocation" ) ? display.content.location : ( ( display.content['@type'] === "messageVenue" ) ? display.content.venue.location : "" ) - } - } - } - - Loader { - id: pollPreviewLoader - active: false - asynchronous: true - width: parent.width -// height: messageListItem.containsLocation ? (item ? item.height : (parent.width * 2 / 3)) : 0 - sourceComponent: Component { - id: pollPreviewComponent - PollPreview { - id: messageLocationPreview - width: parent.width - chatId: chatInformation.id - isOwnMessage: messageListItem.isOwnMessage - message: display - messageItem: messageListItem - } - } } Timer { @@ -951,24 +837,6 @@ Page { } } - Connections { - target: chatModel - onLastReadSentMessageUpdated: { - console.log("[ChatModel] Messages in this chat were read, new last read: " + lastReadSentIndex + ", updating description for index " + index + ", status: " + (index <= lastReadSentIndex)); - messageDateText.text = getMessageStatusText(display, index, lastReadSentIndex); - } - onMessageUpdated: { - if (index === modelIndex) { - console.log("[ChatModel] This message was updated, index " + index + ", updating content..."); - messageDateText.text = getMessageStatusText(display, index, chatView.lastReadSentIndex); - messageText.text = Emoji.emojify(Functions.getMessageText(display, false, messageListItem.isOwnMessage), messageText.font.pixelSize); - if(locationPreviewLoader.active && locationPreviewLoader.status === Loader.Ready) { - locationPreviewLoader.item.locationData = display.content.location; - locationPreviewLoader.item.updatePicture() - } - } - } - } Text { width: parent.width @@ -1003,7 +871,7 @@ Page { anchors.verticalCenter: parent.verticalCenter opacity: chatPage.loading ? 1 : 0 - Behavior on opacity { NumberAnimation {} } + Behavior on opacity { FadeAnimation {} } visible: chatPage.loading InfoLabel { @@ -1066,6 +934,7 @@ Page { Column { id: newMessageColumn spacing: Theme.paddingSmall + width: parent.width - ( 2 * Theme.horizontalPageMargin ) anchors.horizontalCenter: parent.horizontalCenter visible: !chatPage.isChannel @@ -1073,48 +942,6 @@ Page { property string replyToMessageId: "0"; property string editMessageId: "0"; - Component { - id: imagePickerPage - ImagePickerPage { - onSelectedContentPropertiesChanged: { - attachmentOptionsRow.visible = false; - console.log("Selected photo: " + selectedContentProperties.filePath ); - attachmentPreviewRow.fileProperties = selectedContentProperties; - attachmentPreviewRow.isPicture = true; - attachmentPreviewRow.visible = true; - controlSendButton(); - } - } - } - - Component { - id: videoPickerPage - VideoPickerPage { - onSelectedContentPropertiesChanged: { - attachmentOptionsRow.visible = false; - console.log("Selected video: " + selectedContentProperties.filePath ); - attachmentPreviewRow.fileProperties = selectedContentProperties; - attachmentPreviewRow.isVideo = true; - attachmentPreviewRow.visible = true; - controlSendButton(); - } - } - } - - Component { - id: documentPickerPage - DocumentPickerPage { - onSelectedContentPropertiesChanged: { - attachmentOptionsRow.visible = false; - console.log("Selected document: " + selectedContentProperties.filePath ); - attachmentPreviewRow.fileProperties = selectedContentProperties; - attachmentPreviewRow.isDocument = true; - attachmentPreviewRow.visible = true; - controlSendButton(); - } - } - } - InReplyToRow { onInReplyToMessageChanged: { if (inReplyToMessage) { @@ -1134,7 +961,6 @@ Page { id: newMessageInReplyToRow myUserId: chatPage.myUserId - anchors.horizontalCenter: parent.horizontalCenter visible: false } @@ -1149,21 +975,45 @@ Page { id: imageAttachmentButton icon.source: "image://theme/icon-m-image" onClicked: { - pageStack.push(imagePickerPage); + var picker = pageStack.push("Sailfish.Pickers.ImagePickerPage"); + picker.selectedContentPropertiesChanged.connect(function(){ + attachmentOptionsRow.visible = false; + console.log("Selected document: " + picker.selectedContentProperties.filePath ); + attachmentPreviewRow.fileProperties = picker.selectedContentProperties; + attachmentPreviewRow.isDocument = true; + attachmentPreviewRow.visible = true; + controlSendButton(); + }) } } IconButton { id: videoAttachmentButton icon.source: "image://theme/icon-m-video" onClicked: { - pageStack.push(videoPickerPage); + var picker = pageStack.push("Sailfish.Pickers.VideoPickerPage"); + picker.selectedContentPropertiesChanged.connect(function(){ + attachmentOptionsRow.visible = false; + console.log("Selected video: " + picker.selectedContentProperties.filePath ); + attachmentPreviewRow.fileProperties = picker.selectedContentProperties; + attachmentPreviewRow.isVideo = true; + attachmentPreviewRow.visible = true; + controlSendButton(); + }) } } IconButton { id: documentAttachmentButton icon.source: "image://theme/icon-m-document" onClicked: { - pageStack.push(documentPickerPage); + var picker = pageStack.push("Sailfish.Pickers.DocumentPicker"); + picker.selectedContentPropertiesChanged.connect(function(){ + attachmentOptionsRow.visible = false; + console.log("Selected document: " + picker.selectedContentProperties.filePath ); + attachmentPreviewRow.fileProperties = picker.selectedContentProperties; + attachmentPreviewRow.isDocument = true; + attachmentPreviewRow.visible = true; + controlSendButton(); + }) } } @@ -1180,7 +1030,7 @@ Page { } } IconButton { - visible: !chatPage.isPrivateChat && + visible: !chatPage.isPrivateChat && chatGroupInformation && (chatGroupInformation.status["@type"] === "chatMemberStatusCreator" || chatGroupInformation.status["@type"] === "chatMemberStatusAdministrator" || (chatGroupInformation.status["@type"] === "chatMemberStatusMember" && chatInformation.permissions.can_send_polls)) @@ -1222,15 +1072,15 @@ Page { sourceSize.height: height fillMode: Thumbnail.PreserveAspectCrop - mimeType: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.mimeType : "" - source: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.url : "" + mimeType: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.mimeType || "" : "" + source: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.url || "" : "" visible: attachmentPreviewRow.isPicture || attachmentPreviewRow.isVideo } Text { id: attachmentPreviewText font.pixelSize: Theme.fontSizeSmall - text: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.fileName : ""; + text: typeof attachmentPreviewRow.fileProperties !== "undefined" ? attachmentPreviewRow.fileProperties.fileName || "" : ""; anchors.verticalCenter: parent.verticalCenter maximumLineCount: 1 @@ -1407,11 +1257,8 @@ Page { newMessageTextField.focus = false; } } - } - } - } }