feat: send images - UNSAFE -
Sends images but does not clean metadata nor limits file size
This commit is contained in:
parent
1b71e36b48
commit
a32a156651
|
@ -108,6 +108,10 @@ QtObject:
|
|||
self.status.chat.resendMessage(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 userNameOrAlias*(self: ChatsView, pubKey: string): string {.slot.} =
|
||||
|
|
|
@ -218,6 +218,13 @@ proc sendMessage*(self: ChatModel, chatId: string, msg: string, replyTo: string
|
|||
for msg in messages:
|
||||
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) =
|
||||
self.recentStickers.insert(sticker, 0)
|
||||
self.recentStickers = self.recentStickers.deduplicate()
|
||||
|
|
|
@ -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 =
|
||||
callPrivateRPC("sendChatMessage".prefix, %* [
|
||||
{
|
||||
|
|
|
@ -10,7 +10,12 @@ import "./data"
|
|||
StackLayout {
|
||||
id: chatColumnLayout
|
||||
property int chatGroupsListViewCount: 0
|
||||
|
||||
property bool isReply: false
|
||||
property bool isImage: false
|
||||
|
||||
property bool isExtendedInput: isReply || isImage
|
||||
|
||||
property var appSettings
|
||||
property bool isConnected: false
|
||||
Layout.fillHeight: true
|
||||
|
@ -19,6 +24,25 @@ StackLayout {
|
|||
|
||||
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 {
|
||||
spacing: 0
|
||||
|
||||
|
@ -130,10 +154,7 @@ StackLayout {
|
|||
Action {
|
||||
//% "Reply to"
|
||||
text: qsTrId("reply-to")
|
||||
onTriggered: {
|
||||
isReply = true;
|
||||
replyAreaContainer.setup()
|
||||
}
|
||||
onTriggered: showReplyArea()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +187,7 @@ StackLayout {
|
|||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: parent.width
|
||||
height: !isReply ? 70 : 140
|
||||
height: !isExtendedInput ? 70 : 140
|
||||
Layout.preferredHeight: height
|
||||
|
||||
SuggestionBox {
|
||||
|
@ -205,10 +226,27 @@ StackLayout {
|
|||
visible: isReply
|
||||
}
|
||||
|
||||
SendImageArea {
|
||||
id: sendImageArea
|
||||
visible: isImage
|
||||
}
|
||||
|
||||
ChatInput {
|
||||
id: chatInput
|
||||
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.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
|
|
@ -15,7 +15,7 @@ Item {
|
|||
|
||||
Button {
|
||||
id: chatSendBtn
|
||||
visible: txtData.length > 0
|
||||
visible: txtData.length > 0 || chatColumn.isImage
|
||||
width: 30
|
||||
height: 30
|
||||
text: ""
|
||||
|
@ -23,8 +23,15 @@ Item {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
onClicked: {
|
||||
chatsModel.sendMessage(txtData.text, chatColumn.isReply ? SelectedMessage.messageId : "")
|
||||
txtData.text = ""
|
||||
if(chatColumn.isImage){
|
||||
chatsModel.sendImage(sendImageArea.image);
|
||||
chatColumn.hideExtendedArea();
|
||||
}
|
||||
|
||||
if(txtData.text.trim() > 0){
|
||||
chatsModel.sendMessage(txtData.text, chatColumn.isReply ? SelectedMessage.messageId : "")
|
||||
txtData.text = "";
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: parent.enabled ? Style.current.blue : Style.current.grey
|
||||
|
@ -45,7 +52,11 @@ Item {
|
|||
id: emojiIconContainer
|
||||
width: emojiIcon.width + 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.verticalCenter: parent.verticalCenter
|
||||
radius: Style.current.radius
|
||||
|
@ -91,11 +102,11 @@ Item {
|
|||
property bool hovered: false
|
||||
|
||||
id: stickerIconContainer
|
||||
visible: txtData.length == 0
|
||||
visible: !chatColumn.isExtendedInput && txtData.length == 0
|
||||
width: emojiIcon.width + chatButtonsContainer.iconPadding * 2
|
||||
height: emojiIcon.height + chatButtonsContainer.iconPadding * 2
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding
|
||||
anchors.right: imageIconContainer.visible ? imageIconContainer.left : parent.right
|
||||
anchors.rightMargin: Style.current.padding - chatButtonsContainer.iconPadding * (imageIconContainer.visible ? 2 : 1)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: Style.current.radius
|
||||
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 {
|
||||
id: stickersPopup
|
||||
width: 360
|
||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.13
|
|||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtMultimedia 5.13
|
||||
import QtQuick.Dialogs 1.0
|
||||
import "../components"
|
||||
import "../../../../shared"
|
||||
import "../../../../imports"
|
||||
|
@ -34,6 +35,10 @@ Rectangle {
|
|||
function onEnter(event){
|
||||
|
||||
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){
|
||||
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 {
|
||||
id: scrollView
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
|
@ -9,7 +9,7 @@ Item {
|
|||
property string userName: "Jotaro Kujo"
|
||||
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 identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
||||
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg=="
|
||||
property bool isCurrentUser: false
|
||||
property string timestamp: "1234567"
|
||||
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"
|
||||
|
|
|
@ -63,8 +63,7 @@ Rectangle {
|
|||
closeButton.color = Style.current.grey
|
||||
}
|
||||
onClicked: {
|
||||
reset();
|
||||
chatColumn.isReply = false;
|
||||
chatColumn.hideExtendedArea()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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 |
Loading…
Reference in New Issue