diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/ActivityChannelBadge.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/ActivityChannelBadge.qml deleted file mode 100644 index a00c36484c..0000000000 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatComponents/ActivityChannelBadge.qml +++ /dev/null @@ -1,103 +0,0 @@ -import QtQuick 2.13 -import QtGraphicalEffects 1.13 - -import utils 1.0 -import "../../../../../shared" -import "../../../../../shared/panels" -import "../../../../../shared/controls" -import "../../../../../shared/status" -import ".." -import "../../components" - -Rectangle { - property string chatId: "" - property string name: "channelName" - property string identicon - property string responseTo - property string communityId - property int notificationType - property int chatType: chatsModel.channelView.chats.getChannelType(chatId) - property int realChatType: { - if (chatType === Constants.chatTypeCommunity) { - // TODO add a check for private community chats once it is created - return Constants.chatTypePublic - } - return chatType - } - - property string profileImage: realChatType === Constants.chatTypeOneToOne ? appMain.getProfileImage(chatId) || "" : "" - - id: wrapper - height: visible ? 24 : 0 - width: childrenRect.width + 12 - color: Style.current.transparent - border.color: Style.current.borderSecondary - border.width: 1 - radius: 11 - - Loader { - active: true - height: parent.height - anchors.left: parent.left - anchors.leftMargin: 4 - sourceComponent: { - switch (model.notificationType) { - case Constants.activityCenterNotificationTypeMention: return communityOrChannelContentComponent - case Constants.activityCenterNotificationTypeReply: return replyComponent - default: return communityOrChannelContentComponent - } - } - } - - Component { - id: replyComponent - - Item { - property int replyMessageIndex: chatsModel.messageView.getMessageIndex(chatId, responseTo) - property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageView.getMessageData(chatId, replyMessageIndex, "message") : ""; - - - onReplyMessageIndexChanged: { - wrapper.visible = replyMessageIndex > -1 - } - - width: childrenRect.width - height: parent.height - SVGImage { - id: replyIcon - width: 16 - height: 16 - source: Style.svg("reply-small-arrow") - anchors.left: parent.left - anchors.verticalCenter:parent.verticalCenter - } - - StyledTextEdit { - text: Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), Emoji.size.small), false, localAccountSensitiveSettings.useCompactMode) - textFormat: Text.RichText - height: 18 - width: implicitWidth > 300 ? 300 : implicitWidth - clip: true - anchors.left: replyIcon.right - anchors.leftMargin: 4 - color: Style.current.secondaryText - font.weight: Font.Medium - font.pixelSize: 13 - anchors.verticalCenter: parent.verticalCenter - selectByMouse: true - readOnly: true - } - } - } - - Component { - id: communityOrChannelContentComponent - - BadgeContent { - chatId: wrapper.chatId - name: wrapper.name - identicon: wrapper.identicon - communityId: wrapper.communityId - } - } -} diff --git a/ui/app/AppLayouts/Chat/ChatLayout.qml b/ui/app/AppLayouts/Chat/ChatLayout.qml index 323c97ccca..5522b05c3a 100644 --- a/ui/app/AppLayouts/Chat/ChatLayout.qml +++ b/ui/app/AppLayouts/Chat/ChatLayout.qml @@ -7,6 +7,10 @@ import shared 1.0 import shared.panels 1.0 import shared.popups 1.0 import shared.status 1.0 +import shared.views.chat 1.0 + +import StatusQ.Layout 0.1 +import StatusQ.Popups 0.1 import "views" import "panels" @@ -16,9 +20,6 @@ import "helpers" import "controls" import "stores" -import StatusQ.Layout 0.1 -import StatusQ.Popups 0.1 - StatusAppThreePanelLayout { id: root diff --git a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml index ff0ce2df49..347d61fe2b 100644 --- a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml @@ -3,8 +3,10 @@ import QtQuick.Controls 2.3 import utils 1.0 import shared 1.0 +import shared.views 1.0 import shared.panels 1.0 import shared.popups 1.0 +import shared.views.chat 1.0 import "../controls" import "../panels" diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index b6d3f0d2fb..c4e6800831 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -144,4 +144,12 @@ QtObject { function declineRequestToJoinCommunity(id) { chatsModelInst.communities.declineRequestToJoinCommunity(id); } + + function userNameOrAlias(pk) { + return chatsModelInst.userNameOrAlias(pk); + } + + function generateIdenticon(pk) { + return utilsModelInst.generateIdenticon(pk); + } } diff --git a/ui/app/AppLayouts/Chat/views/ActivityCenterGroupRequest.qml b/ui/app/AppLayouts/Chat/views/ActivityCenterGroupRequest.qml index 9a90ce0739..5e1b1d575b 100644 --- a/ui/app/AppLayouts/Chat/views/ActivityCenterGroupRequest.qml +++ b/ui/app/AppLayouts/Chat/views/ActivityCenterGroupRequest.qml @@ -6,6 +6,7 @@ import shared.controls 1.0 import shared 1.0 import shared.panels 1.0 import shared.popups 1.0 +import shared.controls.chat 1.0 import "../controls" import "../panels" diff --git a/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml b/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml index ea7eee63b7..5d5ef19ee4 100644 --- a/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml +++ b/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml @@ -5,7 +5,10 @@ import utils 1.0 import StatusQ.Controls 0.1 +import shared 1.0 +import shared.views 1.0 import shared.popups 1.0 +import shared.views.chat 1.0 import "../controls" import "../panels" diff --git a/ui/app/AppLayouts/Chat/views/ChatColumnView.qml b/ui/app/AppLayouts/Chat/views/ChatColumnView.qml index 9302442a42..d07760ea80 100644 --- a/ui/app/AppLayouts/Chat/views/ChatColumnView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatColumnView.qml @@ -13,6 +13,7 @@ import shared 1.0 import shared.popups 1.0 import shared.status 1.0 import shared.controls 1.0 +import shared.views.chat 1.0 import "../helpers" import "../controls" diff --git a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml index 2a49d82f3f..06e8636243 100644 --- a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml @@ -8,10 +8,12 @@ import QtQuick.Dialogs 1.3 import utils 1.0 import shared 1.0 +import shared.views 1.0 import shared.panels 1.0 import shared.popups 1.0 import shared.status 1.0 import shared.controls 1.0 +import shared.views.chat 1.0 import "../controls" //TODO REMOVE diff --git a/ui/app/AppLayouts/Chat/views/ChatTextView.qml b/ui/app/AppLayouts/Chat/views/ChatTextView.qml index 9b9185a2d3..77094f9c12 100644 --- a/ui/app/AppLayouts/Chat/views/ChatTextView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatTextView.qml @@ -93,7 +93,7 @@ Item { if (link.startsWith('//')) { let pk = link.replace("//", ""); const userProfileImage = appMain.getProfileImage(pk) - openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) + openProfilePopup(root.store.userNameOrAlias(pk), pk, userProfileImage || root.store.generateIdenticon(pk)) return; } diff --git a/ui/app/AppLayouts/Profile/stores/RootStore.qml b/ui/app/AppLayouts/Profile/stores/RootStore.qml index 94f696eff0..25d1acbba2 100644 --- a/ui/app/AppLayouts/Profile/stores/RootStore.qml +++ b/ui/app/AppLayouts/Profile/stores/RootStore.qml @@ -362,4 +362,12 @@ QtObject { function setMessagesFromContactsOnly(checked) { profileModelInst.setMessagesFromContactsOnly(checked) } + + function userNameOrAlias(pk) { + return chatsModelInst.userNameOrAlias(pk); + } + + function generateIdenticon(pk) { + return utilsModelInst.generateIdenticon(pk); + } } diff --git a/ui/app/AppLayouts/Profile/views/AppearanceView.qml b/ui/app/AppLayouts/Profile/views/AppearanceView.qml index 803c593f25..23fe538ede 100644 --- a/ui/app/AppLayouts/Profile/views/AppearanceView.qml +++ b/ui/app/AppLayouts/Profile/views/AppearanceView.qml @@ -5,10 +5,9 @@ import QtQuick.Controls.Universal 2.12 import utils 1.0 import shared 1.0 +import shared.views 1.0 import shared.status 1.0 - -//TODO remove import dependency -import "../../Chat/views" +import shared.views.chat 1.0 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 diff --git a/ui/app/AppLayouts/Profile/views/EnsListView.qml b/ui/app/AppLayouts/Profile/views/EnsListView.qml index e998e080a4..36fb01aeb9 100644 --- a/ui/app/AppLayouts/Profile/views/EnsListView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsListView.qml @@ -11,11 +11,9 @@ import StatusQ.Controls 0.1 import "../popups" import shared 1.0 import shared.panels 1.0 - -//TODO remove these dependencies in imports -import "../../Chat/views" -import "../../Chat/panels" -import "../../Chat/controls" +import shared.views.chat 1.0 +import shared.panels.chat 1.0 +import shared.controls.chat 1.0 Item { id: root diff --git a/ui/app/AppLayouts/Timeline/TimelineLayout.qml b/ui/app/AppLayouts/Timeline/TimelineLayout.qml index fa026358c0..9040135136 100644 --- a/ui/app/AppLayouts/Timeline/TimelineLayout.qml +++ b/ui/app/AppLayouts/Timeline/TimelineLayout.qml @@ -6,12 +6,14 @@ import QtQuick.Layouts 1.13 import utils 1.0 import shared 1.0 +import shared.views 1.0 import shared.status 1.0 +import shared.popups 1.0 import shared.controls 1.0 +import shared.views.chat 1.0 -import "../Chat/views" -import "../Chat/popups" import "../Chat/stores" +import "../Chat/popups" import "stores" import "panels" diff --git a/ui/imports/shared/controls/GasSelector.qml b/ui/imports/shared/controls/GasSelector.qml index cc5cb9c19b..396a6f286c 100644 --- a/ui/imports/shared/controls/GasSelector.qml +++ b/ui/imports/shared/controls/GasSelector.qml @@ -3,12 +3,11 @@ import QtQuick.Controls 2.13 import QtQuick.Layouts 1.13 import utils 1.0 - +import shared.panels 1.0 +import shared.controls 1.0 +import shared.controls.chat 1.0 import StatusQ.Controls 0.1 -import "../panels" -import "." - Item { id: root width: parent.width diff --git a/ui/app/AppLayouts/Chat/controls/DateGroup.qml b/ui/imports/shared/controls/chat/DateGroup.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/DateGroup.qml rename to ui/imports/shared/controls/chat/DateGroup.qml diff --git a/ui/app/AppLayouts/Chat/controls/EmojiReaction.qml b/ui/imports/shared/controls/chat/EmojiReaction.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/EmojiReaction.qml rename to ui/imports/shared/controls/chat/EmojiReaction.qml diff --git a/ui/app/AppLayouts/Chat/controls/FetchMoreMessagesButton.qml b/ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/FetchMoreMessagesButton.qml rename to ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml diff --git a/ui/app/AppLayouts/Chat/controls/GapComponent.qml b/ui/imports/shared/controls/chat/GapComponent.qml similarity index 90% rename from ui/app/AppLayouts/Chat/controls/GapComponent.qml rename to ui/imports/shared/controls/chat/GapComponent.qml index 13cf4385e6..e3a1419afc 100644 --- a/ui/app/AppLayouts/Chat/controls/GapComponent.qml +++ b/ui/imports/shared/controls/chat/GapComponent.qml @@ -17,8 +17,6 @@ Item { font.weight: Font.Medium font.pixelSize: Style.current.primaryTextFontSize color: Style.current.blue - //% "↓ " - //% "Fetch messages" text: qsTrId("fetch-messages") horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter @@ -39,9 +37,7 @@ Item { anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter color: Style.current.secondaryText - //% "before %1" - //% "Between %1 and %2" - text: qsTrId("between--1-and--2").arg(new Date(root.gapFrom*1000)).arg(new Date(root.gapTo*1000)) + text: qsTrId("between--1-and--2").arg(new Date(root.gapFrom * 1000)).arg(new Date(root.gapTo * 1000)) } Separator { anchors.top: fetchDate.bottom diff --git a/ui/imports/shared/controls/GasSelectorButton.qml b/ui/imports/shared/controls/chat/GasSelectorButton.qml similarity index 98% rename from ui/imports/shared/controls/GasSelectorButton.qml rename to ui/imports/shared/controls/chat/GasSelectorButton.qml index 2227c7fa5d..0722f27e58 100644 --- a/ui/imports/shared/controls/GasSelectorButton.qml +++ b/ui/imports/shared/controls/chat/GasSelectorButton.qml @@ -1,13 +1,11 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.13 +import StatusQ.Controls 0.1 import utils 1.0 - -import "../" -import "../panels" - -import StatusQ.Controls 0.1 +import shared.panels 1.0 +import shared.controls 1.0 // TODO: use StatusQ components Rectangle { diff --git a/ui/app/AppLayouts/Chat/controls/MessageBorder.qml b/ui/imports/shared/controls/chat/MessageBorder.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/MessageBorder.qml rename to ui/imports/shared/controls/chat/MessageBorder.qml diff --git a/ui/app/AppLayouts/Chat/controls/MessageMouseArea.qml b/ui/imports/shared/controls/chat/MessageMouseArea.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/MessageMouseArea.qml rename to ui/imports/shared/controls/chat/MessageMouseArea.qml diff --git a/ui/app/AppLayouts/Chat/controls/RectangleCorner.qml b/ui/imports/shared/controls/chat/RectangleCorner.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/RectangleCorner.qml rename to ui/imports/shared/controls/chat/RectangleCorner.qml diff --git a/ui/app/AppLayouts/Chat/controls/Retry.qml b/ui/imports/shared/controls/chat/Retry.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/Retry.qml rename to ui/imports/shared/controls/chat/Retry.qml diff --git a/ui/app/AppLayouts/Chat/controls/SendTransactionButton.qml b/ui/imports/shared/controls/chat/SendTransactionButton.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/SendTransactionButton.qml rename to ui/imports/shared/controls/chat/SendTransactionButton.qml diff --git a/ui/app/AppLayouts/Chat/controls/SentMessage.qml b/ui/imports/shared/controls/chat/SentMessage.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/SentMessage.qml rename to ui/imports/shared/controls/chat/SentMessage.qml diff --git a/ui/app/AppLayouts/Chat/controls/StateBubble.qml b/ui/imports/shared/controls/chat/StateBubble.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/StateBubble.qml rename to ui/imports/shared/controls/chat/StateBubble.qml diff --git a/ui/app/AppLayouts/Chat/controls/UserImage.qml b/ui/imports/shared/controls/chat/UserImage.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/UserImage.qml rename to ui/imports/shared/controls/chat/UserImage.qml diff --git a/ui/app/AppLayouts/Chat/controls/UsernameLabel.qml b/ui/imports/shared/controls/chat/UsernameLabel.qml similarity index 100% rename from ui/app/AppLayouts/Chat/controls/UsernameLabel.qml rename to ui/imports/shared/controls/chat/UsernameLabel.qml diff --git a/ui/imports/shared/controls/chat/qmldir b/ui/imports/shared/controls/chat/qmldir new file mode 100644 index 0000000000..695fe4dc00 --- /dev/null +++ b/ui/imports/shared/controls/chat/qmldir @@ -0,0 +1,14 @@ +FetchMoreMessagesButton 1.0 FetchMoreMessagesButton.qml +GapComponent 1.0 GapComponent.qml +UsernameLabel 1.0 UsernameLabel.qml +DateGroup 1.0 DateGroup.qml +UserImage 1.0 UserImage.qml +MessageMouseArea 1.0 MessageMouseArea.qml +RectangleCorner 1.0 RectangleCorner.qml +SentMessage 1.0 SentMessage.qml +Retry 1.0 Retry.qml +SendTransactionButton 1.0 SendTransactionButton.qml +StateBubble 1.0 StateBubble.qml +GasSelectorButton 1.0 GasSelectorButton.qml +MessageBorder 1.0 MessageBorder.qml +EmojiReaction 1.0 EmojiReaction.qml diff --git a/ui/app/AppLayouts/Chat/panels/AudioPlayerPanel.qml b/ui/imports/shared/panels/chat/AudioPlayerPanel.qml similarity index 100% rename from ui/app/AppLayouts/Chat/panels/AudioPlayerPanel.qml rename to ui/imports/shared/panels/chat/AudioPlayerPanel.qml diff --git a/ui/app/AppLayouts/Chat/panels/ChatButtonsPanel.qml b/ui/imports/shared/panels/chat/ChatButtonsPanel.qml similarity index 100% rename from ui/app/AppLayouts/Chat/panels/ChatButtonsPanel.qml rename to ui/imports/shared/panels/chat/ChatButtonsPanel.qml diff --git a/ui/app/AppLayouts/Chat/panels/ChatReplyPanel.qml b/ui/imports/shared/panels/chat/ChatReplyPanel.qml similarity index 99% rename from ui/app/AppLayouts/Chat/panels/ChatReplyPanel.qml rename to ui/imports/shared/panels/chat/ChatReplyPanel.qml index d790b42b03..5173692021 100644 --- a/ui/app/AppLayouts/Chat/panels/ChatReplyPanel.qml +++ b/ui/imports/shared/panels/chat/ChatReplyPanel.qml @@ -2,13 +2,12 @@ import QtQuick 2.14 import QtQuick.Shapes 1.13 import QtGraphicalEffects 1.13 +import utils 1.0 import shared.controls 1.0 import shared 1.0 import shared.panels 1.0 import shared.status 1.0 -import "../controls" - -import utils 1.0 +import shared.controls.chat 1.0 Loader { id: root diff --git a/ui/imports/shared/panels/chat/ChatTimePanel.qml b/ui/imports/shared/panels/chat/ChatTimePanel.qml new file mode 100644 index 0000000000..a842cffe53 --- /dev/null +++ b/ui/imports/shared/panels/chat/ChatTimePanel.qml @@ -0,0 +1,25 @@ +import QtQuick 2.14 +import shared 1.0 +import shared.panels 1.0 + +import StatusQ.Controls 0.1 as StatusQ +import utils 1.0 + +StyledText { + id: chatTime + color: Style.current.secondaryText + //TODO uncomment when dynamic scoping is cleaned up + //property string timestamp + text: Utils.formatTime(timestamp) + font.pixelSize: Style.current.asideTextFontSize + + StatusQ.StatusToolTip { + visible: hhandler.hovered + text: new Date(parseInt(timestamp, 10)).toLocaleString(Qt.locale(localAppSettings.locale)) + maxWidth: 350 + } + + HoverHandler { + id: hhandler + } +} diff --git a/ui/app/AppLayouts/Chat/panels/EmojiReactionsPanel.qml b/ui/imports/shared/panels/chat/EmojiReactionsPanel.qml similarity index 100% rename from ui/app/AppLayouts/Chat/panels/EmojiReactionsPanel.qml rename to ui/imports/shared/panels/chat/EmojiReactionsPanel.qml diff --git a/ui/imports/shared/panels/chat/qmldir b/ui/imports/shared/panels/chat/qmldir new file mode 100644 index 0000000000..4cbf2afc4e --- /dev/null +++ b/ui/imports/shared/panels/chat/qmldir @@ -0,0 +1,5 @@ +ChatTimePanel 1.0 ChatTimePanel.qml +EmojiReactionsPanel 1.0 EmojiReactionsPanel.qml +ChatReplyPanel 1.0 ChatReplyPanel.qml +ChatButtonsPanel 1.0 ChatButtonsPanel.qml +AudioPlayerPanel 1.0 AudioPlayerPanel.qml diff --git a/ui/app/AppLayouts/Chat/popups/SelectAccountModal.qml b/ui/imports/shared/popups/SelectAccountModal.qml similarity index 100% rename from ui/app/AppLayouts/Chat/popups/SelectAccountModal.qml rename to ui/imports/shared/popups/SelectAccountModal.qml diff --git a/ui/imports/shared/popups/SignTransactionModal.qml b/ui/imports/shared/popups/SignTransactionModal.qml new file mode 100644 index 0000000000..bdd3f7eed6 --- /dev/null +++ b/ui/imports/shared/popups/SignTransactionModal.qml @@ -0,0 +1,377 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtQuick.Layouts 1.13 +import QtQuick.Dialogs 1.3 + +import utils 1.0 +import shared.controls 1.0 + +import StatusQ.Popups 0.1 +import StatusQ.Controls 0.1 + +import shared.views 1.0 +import shared.panels 1.0 +import shared.popups 1.0 +import "../../../app/AppLayouts/Wallet" + +//TODO remove dynamic scoping +StatusModal { + id: root + //% "Send" + header.title: qsTrId("command-button-send") + height: 540 + + property var store + property var selectedAccount + property var selectedRecipient + property var selectedAsset + property var selectedAmount + property var selectedFiatAmount + property bool outgoing: true + + property string trxData: "" + + property alias transactionSigner: transactionSigner + + property var sendTransaction: function(selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOveralLimit, enteredPassword) { + let success = false + if(root.selectedAsset.address == Constants.zeroAddress){ + success = root.store.walletModelInst.transactionsView.transferEth( + selectFromAccount.selectedAccount.address, + selectRecipient.selectedRecipient.address, + root.selectedAmount, + selectedGasLimit, + gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice, + gasSelector.selectedTipLimit, + gasSelector.selectedOverallLimit, + enteredPassword, + stack.uuid) + } else { + success = root.store.walletModelInst.transactionsView.transferTokens( + selectFromAccount.selectedAccount.address, + selectRecipient.selectedRecipient.address, + root.selectedAsset.address, + root.selectedAmount, + selectedGasLimit, + gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice, + gasSelector.selectedTipLimit, + gasSelector.selectedOverallLimit, + enteredPassword, + stack.uuid) + } + + if(!success){ + //% "Invalid transaction parameters" + sendingError.text = qsTrId("invalid-transaction-parameters") + sendingError.open() + } + } + + property MessageDialog sendingError: MessageDialog { + id: sendingError + //% "Error sending the transaction" + title: qsTrId("error-sending-the-transaction") + icon: StandardIcon.Critical + standardButtons: StandardButton.Ok + } + + onClosed: { + stack.pop(groupPreview, StackView.Immediate) + } + + contentItem: Item { + width: root.width + height: childrenRect.height + TransactionStackView { + id: stack + anchors.leftMargin: Style.current.padding + anchors.rightMargin: Style.current.padding + initialItem: groupPreview + isLastGroup: stack.currentGroup === groupSignTx + onGroupActivated: { + root.title = group.headerText + btnNext.text = group.footerText + } + TransactionFormGroup { + id: groupSelectAcct + headerText: { + if(trxData.startsWith("0x095ea7b3")){ + const approveData = JSON.parse(root.store.walletModelInst.tokensView.decodeTokenApproval(selectedRecipient.address, trxData)) + if(approveData.symbol) + //% "Authorize %1 %2" + return qsTrId("authorize--1--2").arg(approveData.amount).arg(approveData.symbol) + } + return qsTrId("command-button-send"); + } + //% "Continue" + footerText: qsTrId("continue") + showNextBtn: false + onBackClicked: function() { + if(validate()) { + stack.pop() + } + } + StatusAccountSelector { + id: selectFromAccount + accounts: root.store.walletModelInst.accountsView.accounts + currency: root.store.walletModelInst.balanceView.defaultCurrency + width: stack.width + selectedAccount: root.selectedAccount + //% "Choose account" + label: qsTrId("choose-account") + showBalanceForAssetSymbol: root.selectedAsset.symbol + minRequiredAssetBalance: parseFloat(root.selectedAmount) + onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() } + } + RecipientSelector { + id: selectRecipient + visible: false + accounts: root.store.walletModelInst.accountsView.accounts + contacts: root.store.profileModelInst.contacts.addedContacts + selectedRecipient: root.selectedRecipient + readOnly: true + } + } + TransactionFormGroup { + id: groupSelectGas + //% "Network fee" + headerText: qsTrId("network-fee") + footerText: qsTr("Continue") + showNextBtn: false + onBackClicked: function() { + stack.pop() + } + GasSelector { + id: gasSelector + anchors.topMargin: Style.current.padding + gasPrice: parseFloat(root.store.walletModelInst.gasView.gasPrice) + getGasEthValue: root.store.walletModelInst.gasView.getGasEthValue + getFiatValue: root.store.walletModelInst.balanceView.getFiatValue + defaultCurrency: root.store.walletModelInst.balanceView.defaultCurrency + width: stack.width + + property var estimateGas: Backpressure.debounce(gasSelector, 600, function() { + if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address && + selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address && + root.selectedAsset && root.selectedAsset.address && + root.selectedAmount)) { + selectedGasLimit = 250000 + defaultGasLimit = selectedGasLimit + return + } + + let gasEstimate = JSON.parse(root.store.walletModelInst.gasView.estimateGas( + selectFromAccount.selectedAccount.address, + selectRecipient.selectedRecipient.address, + root.selectedAsset.address, + root.selectedAmount, + trxData)) + + if (!gasEstimate.success) { + //% "Error estimating gas: %1" + let message = qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message) + + //% ". The transaction will probably fail." + gasEstimateErrorPopup.confirmationText = message + qsTrId("--the-transaction-will-probably-fail-") + gasEstimateErrorPopup.open() + return + } + selectedGasLimit = gasEstimate.result + defaultGasLimit = selectedGasLimit + }) + } + GasValidator { + id: gasValidator + anchors.top: gasSelector.bottom + selectedAccount: selectFromAccount.selectedAccount + selectedAmount: parseFloat(root.selectedAmount) + selectedAsset: root.selectedAsset + selectedGasEthValue: gasSelector.selectedGasEthValue + } + } + + TransactionFormGroup { + id: groupPreview + //% "Transaction preview" + headerText: qsTrId("transaction-preview") + //% "Sign with password" + footerText: qsTrId("sign-with-password") + showBackBtn: false + onNextClicked: function() { + stack.push(groupSignTx, StackView.Immediate) + } + isValid: groupSelectAcct.isValid && groupSelectGas.isValid && pvwTransaction.isValid + + TransactionPreview { + id: pvwTransaction + width: stack.width + fromAccount: selectFromAccount.selectedAccount + gas: { + "value": gasSelector.selectedGasEthValue, + "symbol": "ETH", + "fiatValue": gasSelector.selectedGasFiatValue + } + toAccount: selectRecipient.selectedRecipient + asset: root.selectedAsset + amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount } + currency: root.store.walletModelInst.balanceView.defaultCurrency + isFromEditable: false + trxData: root.trxData + isGasEditable: true + fromValid: balanceValidator.isValid + gasValid: gasValidator.isValid + onFromClicked: { stack.push(groupSelectAcct, StackView.Immediate) } + onGasClicked: { stack.push(groupSelectGas, StackView.Immediate) } + } + BalanceValidator { + id: balanceValidator + anchors.top: pvwTransaction.bottom + anchors.horizontalCenter: parent.horizontalCenter + account: selectFromAccount.selectedAccount + amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0 + asset: root.selectedAsset + } + GasValidator { + id: gasValidator2 + anchors.top: balanceValidator.visible ? balanceValidator.bottom : pvwTransaction.bottom + anchors.topMargin: balanceValidator.visible ? 5 : 0 + anchors.horizontalCenter: parent.horizontalCenter + selectedAccount: selectFromAccount.selectedAccount + selectedAmount: parseFloat(root.selectedAmount) + selectedAsset: root.selectedAsset + selectedGasEthValue: gasSelector.selectedGasEthValue + } + } + TransactionFormGroup { + id: groupSignTx + //% "Sign with password" + headerText: qsTrId("sign-with-password") + //% "Send %1 %2" + footerText: qsTrId("send--1--2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "") + onBackClicked: function() { + stack.pop() + } + + TransactionSigner { + id: transactionSigner + width: stack.width + signingPhrase: root.store.walletModelInst.utilsView.signingPhrase + } + } + } + } + + leftButtons: [ + StatusRoundButton { + id: btnBack + icon.name: "arrow-right" + icon.width: 20 + icon.height: 16 + icon.rotation: 180 + visible: stack.currentGroup.showBackBtn + enabled: stack.currentGroup.isValid || stack.isLastGroup + onClicked: { + if (typeof stack.currentGroup.onBackClicked === "function") { + return stack.currentGroup.onBackClicked() + } + stack.back() + } + } + ] + + rightButtons: [ + StatusButton { + id: btnNext + anchors.right: parent.right + //% "Next" + text: qsTrId("next") + enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending + visible: stack.currentGroup.showNextBtn + onClicked: { + const validity = stack.currentGroup.validate() + if (validity.isValid && !validity.isPending) { + if (stack.isLastGroup) { + return root.sendTransaction(gasSelector.selectedGasLimit, + gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice, + gasSelector.selectedTipLimit, + gasSelector.selectedOverallLimit, + transactionSigner.enteredPassword) + } + + if(gasSelector.eip1599Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){ + if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){ + openPopup(transactionSettingsConfirmationPopupComponent, { + currentBaseFee: gasSelector.latestBaseFeeGwei, + currentMinimumTip: gasSelector.perGasTipLimitFloor, + currentAverageTip: gasSelector.perGasTipLimitAverage, + tipLimit: gasSelector.selectedTipLimit, + suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO: + priceLimit: gasSelector.selectedOverallLimit, + suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor, + showPriceLimitWarning: gasSelector.showPriceLimitWarning, + showTipLimitWarning: gasSelector.showTipLimitWarning, + onConfirm: function(){ + stack.next(); + } + }) + return + } + } + + + if (typeof stack.currentGroup.onNextClicked === "function") { + return stack.currentGroup.onNextClicked() + } + stack.next() + } + } + } + ] + + Component { + id: transactionSettingsConfirmationPopupComponent + TransactionSettingsConfirmationPopup { + + } + } + + Connections { + target: root.store.walletModelInst.transactionsView + onTransactionWasSent: { + try { + let response = JSON.parse(txResult) + if (response.uuid !== stack.uuid) + return + + let transactionId = response.result + + if (!response.success) { + if (Utils.isInvalidPasswordMessage(transactionId)){ + //% "Wrong password" + transactionSigner.validationError = qsTrId("wrong-password") + return + } + sendingError.text = transactionId + return sendingError.open() + } + + chatsModel.transactions.acceptRequestTransaction(transactionId, + messageId, + root.store.profileModelInst.profile.pubKey + transactionId.substr(2)) + + //% "Transaction pending..." + toastMessage.title = qsTrId("ens-transaction-pending") + toastMessage.source = Style.svg("loading") + toastMessage.iconColor = Style.current.primary + toastMessage.iconRotates = true + toastMessage.link = `${root.store.walletModelInst.utilsView.etherscanLink}/${transactionId}` + toastMessage.open() + + root.close() + } catch (e) { + console.error('Error parsing the response', e) + } + } + } +} + diff --git a/ui/imports/shared/popups/qmldir b/ui/imports/shared/popups/qmldir index 91b5e1e2fb..57a6715770 100644 --- a/ui/imports/shared/popups/qmldir +++ b/ui/imports/shared/popups/qmldir @@ -11,3 +11,5 @@ ToastMessage 1.0 ToastMessage.qml TransactionSettingsConfirmationPopup 1.0 TransactionSettingsConfirmationPopup.qml UnblockContactConfirmationDialog 1.0 UnblockContactConfirmationDialog.qml UserStatusContextMenu 1.0 UserStatusContextMenu.qml +SignTransactionModal 1.0 SignTransactionModal.qml +SelectAccountModal 1.0 SelectAccountModal.qml diff --git a/ui/app/AppLayouts/Chat/views/AcceptTransactionView.qml b/ui/imports/shared/views/chat/AcceptTransactionView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/AcceptTransactionView.qml rename to ui/imports/shared/views/chat/AcceptTransactionView.qml index 12f2f1fb01..21f0700198 100644 --- a/ui/app/AppLayouts/Chat/views/AcceptTransactionView.qml +++ b/ui/imports/shared/views/chat/AcceptTransactionView.qml @@ -5,8 +5,6 @@ import shared.popups 1.0 import shared.panels 1.0 import shared.controls 1.0 -import "../popups" - import utils 1.0 //TODO remove dynamic scoping diff --git a/ui/app/AppLayouts/Chat/views/ChannelIdentifierView.qml b/ui/imports/shared/views/chat/ChannelIdentifierView.qml similarity index 100% rename from ui/app/AppLayouts/Chat/views/ChannelIdentifierView.qml rename to ui/imports/shared/views/chat/ChannelIdentifierView.qml diff --git a/ui/imports/shared/views/chat/ChatTextView.qml b/ui/imports/shared/views/chat/ChatTextView.qml new file mode 100644 index 0000000000..04b3faa7ab --- /dev/null +++ b/ui/imports/shared/views/chat/ChatTextView.qml @@ -0,0 +1,180 @@ +import QtQuick 2.13 +import QtGraphicalEffects 1.0 + +import shared 1.0 +import shared.panels 1.0 +import shared.controls 1.0 +import utils 1.0 + +Item { + id: root + + property var store + //TODO remove when dynamic scoping is cleaned up + property var messageStore + property bool longChatText: true + property bool veryLongChatText: !!root.store ? root.store.chatsModelInst.plainText(message).length > + (localAccountSensitiveSettings.useCompactMode ? Constants.limitLongChatTextCompactMode : Constants.limitLongChatText) : false + property bool readMore: false + property alias textField: chatText + + signal linkActivated(url link) + property alias hoveredLink: chatText.hoveredLink + property bool linkHovered: chatText.hoveredLink !== "" + + z: 51 + + implicitHeight: visible ? (showMoreLoader.active ? childrenRect.height - 10 : chatText.height) : 0 + + // This function is to avoid the binding loop warning + function setWidths() { + if (longChatText) { + root.width = 0; + chatText.width = Qt.binding(function () {return root.width}) + } else { + chatText.width = Qt.binding(function () {return chatText.implicitWidth}) + root.width = Qt.binding(function () {return chatText.width}) + } + } + + Component.onCompleted: { + root.setWidths() + } + + StyledTextEdit { + id: chatText + visible: !showMoreLoader.active || root.readMore + textFormat: Text.RichText + wrapMode: Text.Wrap + font.pixelSize: Style.current.primaryTextFontSize + readOnly: true + selectByMouse: true + color: Style.current.textColor + height: root.veryLongChatText && !root.readMore ? Math.min(implicitHeight, 200) : implicitHeight + clip: height < implicitHeight + onLinkActivated: { + + root.linkActivated(link) + if(link.startsWith("#")) { + const channelName = link.substring(1); + const foundChannelObj = root.store.chatsModelInst.getChannel(channelName); + + if (!foundChannelObj) + { + root.store.chatsModelInst.channelView.joinPublicChat(channelName) + if(root.store.chatsModelInst.communities.activeCommunity.active) + { + root.store.chatsModelInst.channelView.joinPublicChat(channelName) + appMain.changeAppSectionBySectionType(Constants.appSection.chat) + } + return + } + + let obj = JSON.parse(foundChannelObj) + + if(obj.chatType === -1 || obj.chatType === Constants.chatTypePublic) + { + if(root.store.chatsModelInst.communities.activeCommunity.active) { + root.store.chatsModelInst.channelView.joinPublicChat(channelName) + appMain.changeAppSectionBySectionType(Constants.appSection.chat) + } + root.store.chatsModelInst.channelView.setActiveChannel(channelName); + } + else if(obj.communityId === root.store.chatsModelInst.communities.activeCommunity.id && + obj.chatType === Constants.chatTypeCommunity && + root.store.chatsModelInst.channelView.activeChannel.id !== obj.id + ) + { + root.store.chatsModelInst.channelView.setActiveChannel(channelName); + } + + return + } + + if (link.startsWith('//')) { + let pk = link.replace("//", ""); + const userProfileImage = appMain.getProfileImage(pk) + openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) + return; + } + + const data = Utils.getLinkDataForStatusLinks(link) + if (data && data.callback) { + return data.callback() + } + + + appMain.openLink(link) + } + + onLinkHovered: { + cursorShape: Qt.PointingHandCursor + } + + text: { + if(contentType === Constants.stickerType) return ""; + let msg = Utils.linkifyAndXSS(message); + if(isEmoji) { + return Emoji.parse(msg, Emoji.size.middle); + } else { + if(isEdited){ + let index = msg.endsWith("code>") ? msg.length : msg.length - 4 + return Utils.getMessageWithStyle(Emoji.parse(msg.slice(0, index) + Constants.editLabel + msg.slice(index)), localAccountSensitiveSettings.useCompactMode, isCurrentUser, hoveredLink) + } + return Utils.getMessageWithStyle(Emoji.parse(msg), localAccountSensitiveSettings.useCompactMode, isCurrentUser, hoveredLink) + } + } + } + + Loader { + id: mask + anchors.fill: chatText + active: showMoreLoader.active + visible: false + sourceComponent: LinearGradient { + start: Qt.point(0, 0) + end: Qt.point(0, chatText.height) + gradient: Gradient { + GradientStop { position: 0.0; color: "white" } + GradientStop { position: 0.85; color: "white" } + GradientStop { position: 1; color: "transparent" } + } + } + } + + Loader { + id: opMask + active: showMoreLoader.active && !root.readMore + anchors.fill: chatText + sourceComponent: OpacityMask { + source: chatText + maskSource: mask + } + } + + Loader { + id: showMoreLoader + active: root.veryLongChatText + anchors.top: chatText.bottom + anchors.topMargin: - Style.current.padding + anchors.horizontalCenter: parent.horizontalCenter + sourceComponent: Component { + SVGImage { + id: emojiImage + width: 256 + height: 44 + fillMode: Image.PreserveAspectFit + source: Style.svg("read-more") + z: 100 + rotation: root.readMore ? 180 : 0 + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + root.readMore = !root.readMore + } + } + } + } + } +} diff --git a/ui/app/AppLayouts/Chat/views/CompactMessageView.qml b/ui/imports/shared/views/chat/CompactMessageView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/CompactMessageView.qml rename to ui/imports/shared/views/chat/CompactMessageView.qml index 2219b183a8..c3912883a3 100644 --- a/ui/app/AppLayouts/Chat/views/CompactMessageView.qml +++ b/ui/imports/shared/views/chat/CompactMessageView.qml @@ -5,12 +5,11 @@ import utils 1.0 import shared.panels 1.0 import shared.status 1.0 import shared.controls 1.0 +import shared.panels.chat 1.0 +import shared.controls.chat 1.0 import StatusQ.Controls 0.1 as StatusQControls -import "../panels" -import "../controls" - Item { id: root property var store diff --git a/ui/app/AppLayouts/Chat/views/InvitationBubbleView.qml b/ui/imports/shared/views/chat/InvitationBubbleView.qml similarity index 100% rename from ui/app/AppLayouts/Chat/views/InvitationBubbleView.qml rename to ui/imports/shared/views/chat/InvitationBubbleView.qml diff --git a/ui/app/AppLayouts/Chat/views/LinksMessageView.qml b/ui/imports/shared/views/chat/LinksMessageView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/LinksMessageView.qml rename to ui/imports/shared/views/chat/LinksMessageView.qml index ea476d235c..7422edef2a 100644 --- a/ui/app/AppLayouts/Chat/views/LinksMessageView.qml +++ b/ui/imports/shared/views/chat/LinksMessageView.qml @@ -8,10 +8,10 @@ import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Controls 0.1 -import shared.panels 1.0 import shared.status 1.0 -import "../controls" -import "../panels" +import shared.panels 1.0 +import shared.panels.chat 1.0 +import shared.controls.chat 1.0 Column { id: root diff --git a/ui/app/AppLayouts/Chat/views/MessageContextMenuView.qml b/ui/imports/shared/views/chat/MessageContextMenuView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/MessageContextMenuView.qml rename to ui/imports/shared/views/chat/MessageContextMenuView.qml index 6f4e11dd58..b74ba30f86 100644 --- a/ui/app/AppLayouts/Chat/views/MessageContextMenuView.qml +++ b/ui/imports/shared/views/chat/MessageContextMenuView.qml @@ -12,7 +12,7 @@ import shared 1.0 import shared.panels 1.0 import shared.popups 1.0 import shared.status 1.0 -import "../controls" +import shared.controls.chat 1.0 StatusPopupMenu { id: root diff --git a/ui/app/AppLayouts/Chat/views/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/MessageView.qml rename to ui/imports/shared/views/chat/MessageView.qml index 148fe6fa9f..f7a563aec7 100644 --- a/ui/app/AppLayouts/Chat/views/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -2,16 +2,14 @@ import QtQuick 2.13 import StatusQ.Components 0.1 +import utils 1.0 import shared.panels 1.0 import shared.status 1.0 import shared.controls 1.0 +import shared.panels.chat 1.0 +import shared.views.chat 1.0 +import shared.controls.chat 1.0 -import utils 1.0 -import "../panels" -import "../views" -import "../controls" - -//TODO RE-WRITE THIS COMPONENT Column { id: root width: parent.width diff --git a/ui/app/AppLayouts/Chat/views/NormalMessageView.qml b/ui/imports/shared/views/chat/NormalMessageView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/NormalMessageView.qml rename to ui/imports/shared/views/chat/NormalMessageView.qml index c37755bb1d..afbaea6554 100644 --- a/ui/app/AppLayouts/Chat/views/NormalMessageView.qml +++ b/ui/imports/shared/views/chat/NormalMessageView.qml @@ -1,12 +1,10 @@ import QtQuick 2.13 +import utils 1.0 import shared 1.0 import shared.status 1.0 - -import utils 1.0 - -import "../panels" -import "../views" -import "../controls" +import shared.views.chat 1.0 +import shared.panels.chat 1.0 +import shared.controls.chat 1.0 Item { id: root diff --git a/ui/app/AppLayouts/Chat/views/StatusUpdateView.qml b/ui/imports/shared/views/chat/StatusUpdateView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/StatusUpdateView.qml rename to ui/imports/shared/views/chat/StatusUpdateView.qml index 54be1ca071..27c423fa53 100644 --- a/ui/app/AppLayouts/Chat/views/StatusUpdateView.qml +++ b/ui/imports/shared/views/chat/StatusUpdateView.qml @@ -1,13 +1,12 @@ import QtQuick 2.3 import QtGraphicalEffects 1.13 + +import utils 1.0 import shared 1.0 import shared.panels 1.0 import shared.status 1.0 - -import utils 1.0 - -import "../panels" -import "../controls" +import shared.panels.chat 1.0 +import shared.controls.chat 1.0 import StatusQ.Controls 0.1 diff --git a/ui/app/AppLayouts/Chat/views/TransactionBubbleView.qml b/ui/imports/shared/views/chat/TransactionBubbleView.qml similarity index 99% rename from ui/app/AppLayouts/Chat/views/TransactionBubbleView.qml rename to ui/imports/shared/views/chat/TransactionBubbleView.qml index 32877821ee..eed0499966 100644 --- a/ui/app/AppLayouts/Chat/views/TransactionBubbleView.qml +++ b/ui/imports/shared/views/chat/TransactionBubbleView.qml @@ -2,10 +2,9 @@ import QtQuick 2.3 import utils 1.0 import shared 1.0 import shared.panels 1.0 - -import "../views" -import "../popups" -import "../controls" +import shared.popups 1.0 +import shared.views.chat 1.0 +import shared.controls.chat 1.0 Item { id: root diff --git a/ui/imports/shared/views/chat/qmldir b/ui/imports/shared/views/chat/qmldir new file mode 100644 index 0000000000..56998db150 --- /dev/null +++ b/ui/imports/shared/views/chat/qmldir @@ -0,0 +1,10 @@ +ChannelIdentifierView 1.0 ChannelIdentifierView.qml +ChatTextView 1.0 ChatTextView.qml +MessageView 1.0 MessageView.qml +StatusUpdateView 1.0 StatusUpdateView.qml +TransactionBubbleView 1.0 TransactionBubbleView.qml +LinksMessageView 1.0 LinksMessageView.qml +InvitationBubbleView 1.0 InvitationBubbleView.qml +NormalMessageView 1.0 NormalMessageView.qml +CompactMessageView 1.0 CompactMessageView.qml +MessageContextMenuView 1.0 MessageContextMenuView.qml