feat: send images - UNSAFE -

Sends images but does not clean metadata nor limits file size
This commit is contained in:
Richard Ramos 2020-07-20 13:04:33 -04:00 committed by Iuri Matias
parent 1b71e36b48
commit a32a156651
10 changed files with 223 additions and 16 deletions

View File

@ -108,6 +108,10 @@ QtObject:
self.status.chat.resendMessage(messageId) self.status.chat.resendMessage(messageId)
self.messageList[chatId].resetTimeOut(messageId) self.messageList[chatId].resetTimeOut(messageId)
proc sendImage*(self: ChatsView, imagePath: string) {.slot.} =
let image = replace(imagePath, "file://", "")
self.status.chat.sendImage(self.activeChannel.id, image)
proc activeChannelChanged*(self: ChatsView) {.signal.} proc activeChannelChanged*(self: ChatsView) {.signal.}
proc userNameOrAlias*(self: ChatsView, pubKey: string): string {.slot.} = proc userNameOrAlias*(self: ChatsView, pubKey: string): string {.slot.} =

View File

@ -218,6 +218,13 @@ proc sendMessage*(self: ChatModel, chatId: string, msg: string, replyTo: string
for msg in messages: for msg in messages:
self.events.emit("sendingMessage", MessageArgs(id: msg.id, channel: msg.chatId)) self.events.emit("sendingMessage", MessageArgs(id: msg.id, channel: msg.chatId))
proc sendImage*(self: ChatModel, chatId: string, image: string) =
var response = status_chat.sendImageMessage(chatId, image)
var (chats, messages) = self.processChatUpdate(parseJson(response))
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
for msg in messages:
self.events.emit("sendingMessage", MessageArgs(id: msg.id, channel: msg.chatId))
proc addStickerToRecent*(self: ChatModel, sticker: Sticker, save: bool = false) = proc addStickerToRecent*(self: ChatModel, sticker: Sticker, save: bool = false) =
self.recentStickers.insert(sticker, 0) self.recentStickers.insert(sticker, 0)
self.recentStickers = self.recentStickers.deduplicate() self.recentStickers = self.recentStickers.deduplicate()

View File

@ -83,6 +83,16 @@ proc sendChatMessage*(chatId: string, msg: string, replyTo: string): string =
} }
]) ])
proc sendImageMessage*(chatId: string, image: string): string =
callPrivateRPC("sendChatMessage".prefix, %* [
{
"chatId": chatId,
"contentType": ContentType.Image.int,
"imagePath": image,
"text": "Update to latest version to see a nice image here!"
}
])
proc sendStickerMessage*(chatId: string, sticker: Sticker): string = proc sendStickerMessage*(chatId: string, sticker: Sticker): string =
callPrivateRPC("sendChatMessage".prefix, %* [ callPrivateRPC("sendChatMessage".prefix, %* [
{ {

View File

@ -10,7 +10,12 @@ import "./data"
StackLayout { StackLayout {
id: chatColumnLayout id: chatColumnLayout
property int chatGroupsListViewCount: 0 property int chatGroupsListViewCount: 0
property bool isReply: false property bool isReply: false
property bool isImage: false
property bool isExtendedInput: isReply || isImage
property var appSettings property var appSettings
property bool isConnected: false property bool isConnected: false
Layout.fillHeight: true Layout.fillHeight: true
@ -19,6 +24,25 @@ StackLayout {
currentIndex: chatsModel.activeChannelIndex > -1 && chatGroupsListViewCount > 0 ? 0 : 1 currentIndex: chatsModel.activeChannelIndex > -1 && chatGroupsListViewCount > 0 ? 0 : 1
function showReplyArea(){
isReply = true;
isImage = false;
replyAreaContainer.setup()
}
function showImageArea(imagePath){
isImage = true;
isReply = false;
sendImageArea.image = imagePath[0];
}
function hideExtendedArea(){
isImage = false;
isReply = false;
replyAreaContainer.setup();
sendImageArea.image = "";
}
ColumnLayout { ColumnLayout {
spacing: 0 spacing: 0
@ -130,10 +154,7 @@ StackLayout {
Action { Action {
//% "Reply to" //% "Reply to"
text: qsTrId("reply-to") text: qsTrId("reply-to")
onTriggered: { onTriggered: showReplyArea()
isReply = true;
replyAreaContainer.setup()
}
} }
} }
@ -166,7 +187,7 @@ StackLayout {
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
height: !isReply ? 70 : 140 height: !isExtendedInput ? 70 : 140
Layout.preferredHeight: height Layout.preferredHeight: height
SuggestionBox { SuggestionBox {
@ -205,10 +226,27 @@ StackLayout {
visible: isReply visible: isReply
} }
SendImageArea {
id: sendImageArea
visible: isImage
}
ChatInput { ChatInput {
id: chatInput id: chatInput
height: 40 height: 40
anchors.top: !isReply ? inputArea.top : replyAreaContainer.bottom anchors.top: {
if(!isExtendedInput){
return inputArea.top;
}
if(isReply){
return replyAreaContainer.bottom;
}
if(isImage){
return sendImageArea.bottom;
}
}
anchors.topMargin: 4 anchors.topMargin: 4
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@ -15,7 +15,7 @@ Item {
Button { Button {
id: chatSendBtn id: chatSendBtn
visible: txtData.length > 0 visible: txtData.length > 0 || chatColumn.isImage
width: 30 width: 30
height: 30 height: 30
text: "" text: ""
@ -23,8 +23,15 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right anchors.right: parent.right
onClicked: { onClicked: {
if(chatColumn.isImage){
chatsModel.sendImage(sendImageArea.image);
chatColumn.hideExtendedArea();
}
if(txtData.text.trim() > 0){
chatsModel.sendMessage(txtData.text, chatColumn.isReply ? SelectedMessage.messageId : "") chatsModel.sendMessage(txtData.text, chatColumn.isReply ? SelectedMessage.messageId : "")
txtData.text = "" txtData.text = "";
}
} }
background: Rectangle { background: Rectangle {
color: parent.enabled ? Style.current.blue : Style.current.grey color: parent.enabled ? Style.current.blue : Style.current.grey
@ -45,7 +52,11 @@ Item {
id: emojiIconContainer id: emojiIconContainer
width: emojiIcon.width + chatButtonsContainer.iconPadding * 2 width: emojiIcon.width + chatButtonsContainer.iconPadding * 2
height: emojiIcon.height + chatButtonsContainer.iconPadding * 2 height: emojiIcon.height + chatButtonsContainer.iconPadding * 2
anchors.right: txtData.length == 0 ? stickerIconContainer.left : chatSendBtn.left anchors.right: {
if(stickerIconContainer.visible) return stickerIconContainer.left;
if(imageIconContainer.visible) return imageIconContainer.left;
return chatSendBtn.left;
}
anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding * 2 anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding * 2
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
radius: Style.current.radius radius: Style.current.radius
@ -91,11 +102,11 @@ Item {
property bool hovered: false property bool hovered: false
id: stickerIconContainer id: stickerIconContainer
visible: txtData.length == 0 visible: !chatColumn.isExtendedInput && txtData.length == 0
width: emojiIcon.width + chatButtonsContainer.iconPadding * 2 width: emojiIcon.width + chatButtonsContainer.iconPadding * 2
height: emojiIcon.height + chatButtonsContainer.iconPadding * 2 height: emojiIcon.height + chatButtonsContainer.iconPadding * 2
anchors.right: parent.right anchors.right: imageIconContainer.visible ? imageIconContainer.left : parent.right
anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding * (imageIconContainer.visible ? 2 : 1)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
radius: Style.current.radius radius: Style.current.radius
color: hovered ? Style.current.lightBlue : Style.current.transparent color: hovered ? Style.current.lightBlue : Style.current.transparent
@ -136,6 +147,50 @@ Item {
} }
} }
Rectangle {
property bool hovered: false
visible: !chatColumn.isExtendedInput && (chatsModel.activeChannel.chatType === Constants.chatTypePrivateGroupChat || chatsModel.activeChannel.chatType === Constants.chatTypeOneToOne)
id: imageIconContainer
width: emojiIcon.width + chatButtonsContainer.iconPadding * 2
height: emojiIcon.height + chatButtonsContainer.iconPadding * 2
anchors.right: chatSendBtn.visible ? chatSendBtn.left : parent.right
anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding
anchors.verticalCenter: parent.verticalCenter
radius: Style.current.radius
color: hovered ? Style.current.lightBlue : Style.current.transparent
Image {
id: imageIcon
width: 20
height: 20
fillMode: Image.PreserveAspectFit
source: "../../../img/images_icon.svg"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
ColorOverlay {
anchors.fill: imageIcon
source: imageIcon
color: imageIconContainer.hovered ? Style.current.blue : Style.current.transparent
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onEntered: {
imageIconContainer.hovered = true
}
onExited: {
imageIconContainer.hovered = false
}
onClicked: {
imageDialog.open();
}
}
}
StickersPopup { StickersPopup {
id: stickersPopup id: stickersPopup
width: 360 width: 360

View File

@ -2,6 +2,7 @@ import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import QtMultimedia 5.13 import QtMultimedia 5.13
import QtQuick.Dialogs 1.0
import "../components" import "../components"
import "../../../../shared" import "../../../../shared"
import "../../../../imports" import "../../../../imports"
@ -34,6 +35,10 @@ Rectangle {
function onEnter(event){ function onEnter(event){
if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
if(chatColumn.isImage){
chatsModel.sendImage(sendImageArea.image);
chatColumn.hideExtendedArea();
}
if(txtData.text.trim().length > 0){ if(txtData.text.trim().length > 0){
let msg = interpretMessage(txtData.text.trim()) let msg = interpretMessage(txtData.text.trim())
@ -46,6 +51,22 @@ Rectangle {
} }
} }
FileDialog {
id: imageDialog
title: qsTr("Please choose an image")
folder: shortcuts.pictures
nameFilters: [
qsTr("Image files (*.jpg *.jpeg *.png)")
]
onAccepted: {
chatColumn.showImageArea(imageDialog.fileUrls);
txtData.forceActiveFocus();
}
onRejected: {
chatColumn.hideExtendedArea();
}
}
ScrollView { ScrollView {
id: scrollView id: scrollView
anchors.bottom: parent.bottom anchors.bottom: parent.bottom

View File

@ -9,7 +9,7 @@ Item {
property string userName: "Jotaro Kujo" property string userName: "Jotaro Kujo"
property string message: "That's right. We're friends... Of justice, that is." property string message: "That's right. We're friends... Of justice, that is."
property string plainText: "That's right. We're friends... Of justice, that is." property string plainText: "That's right. We're friends... Of justice, that is."
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg=="
property bool isCurrentUser: false property bool isCurrentUser: false
property string timestamp: "1234567" property string timestamp: "1234567"
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v" property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"

View File

@ -63,8 +63,7 @@ Rectangle {
closeButton.color = Style.current.grey closeButton.color = Style.current.grey
} }
onClicked: { onClicked: {
reset(); chatColumn.hideExtendedArea()
chatColumn.isReply = false;
} }
} }
} }

View File

@ -0,0 +1,69 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../../../../imports"
import "../../../../shared"
import "./"
Rectangle {
id: sendImageArea
height: 70
property string image: ""
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
color: "#00000000"
Rectangle {
id: closeButton
height: 32
width: 32
anchors.top: parent.top
anchors.topMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
anchors.right: parent.right
radius: 8
SVGImage {
id: closeModalImg
source: "../../../../shared/img/close.svg"
width: 25
height: 25
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: closeImageArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onExited: {
closeButton.color = Style.current.white
}
onEntered: {
closeButton.color = Style.current.grey
}
onClicked: {
chatColumn.hideExtendedArea();
}
}
}
Image {
id: chatImage
width: 36
height: 36
anchors.topMargin: 20
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: parent.top
fillMode: Image.PreserveAspectFit
source: image
mipmap: true
smooth: false
antialiasing: true
}
}

View File

@ -0,0 +1,4 @@
<svg width="20" height="18" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.5 6.5C16.5 8.15685 15.1569 9.5 13.5 9.5C11.8431 9.5 10.5 8.15685 10.5 6.5C10.5 4.84315 11.8431 3.5 13.5 3.5C15.1569 3.5 16.5 4.84315 16.5 6.5ZM15 6.5C15 7.32843 14.3284 8 13.5 8C12.6716 8 12 7.32843 12 6.5C12 5.67157 12.6716 5 13.5 5C14.3284 5 15 5.67157 15 6.5Z" fill="#939BA1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 0C1.79086 0 0 1.79086 0 4V14C0 16.2091 1.79086 18 4 18H16C18.2091 18 20 16.2091 20 14V4C20 1.79086 18.2091 0 16 0H4ZM16 1.5H4C2.61929 1.5 1.5 2.61929 1.5 4V7.23223C1.5 7.67768 2.03857 7.90077 2.35355 7.58579L3.76256 6.17678C4.44598 5.49336 5.55402 5.49336 6.23744 6.17678L16.3181 16.2575C16.4372 16.3765 16.6094 16.4311 16.7695 16.3793C17.7737 16.0548 18.5 15.1122 18.5 14V4C18.5 2.61929 17.3807 1.5 16 1.5ZM1.53033 10.5303C1.51153 10.5491 1.5 10.5742 1.5 10.6008V14C1.5 15.3807 2.61929 16.5 4 16.5H13.2322C13.6777 16.5 13.9008 15.9614 13.5858 15.6464L5.17678 7.23744C5.07914 7.1398 4.92085 7.13981 4.82322 7.23744L1.53033 10.5303Z" fill="#939BA1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB