refactoring (desktop/chat) Message component

Moved Message component & dependencies  to shared
for usage import shared.views.chat 1.0 and accordingly
import shared.controls/panels.chat 1.0

Closes #3927
This commit is contained in:
Alexandra Betouni 2021-10-28 23:23:30 +03:00 committed by Jakub
parent 7ee7ba5ebe
commit c0450f0580
50 changed files with 682 additions and 164 deletions

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -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

View File

@ -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)
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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
}
}
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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