Compare commits

...

10 Commits

Author SHA1 Message Date
69400bee2a misc: bump daemon submodule
Brings in some changes intended to correct/improve CI building
on Windows.

https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1027
Change-Id: I7047cd343b5711adaf4c992b99dc07097e9ff05b
2024-07-26 14:50:10 -04:00
0e07f9cee7 JamiIdentifier: fix binding for Jami ID
GitLab: #1805
Change-Id: Ic847bb61ccb2c75873d91a35cd851caaedaf518d
2024-07-23 11:20:52 -04:00
d2eba1d91e chatview: fix datatransfer messages not showing
99254f8d02 introduced 2 issues:
- transfer messages not notifying the UI
- some file URLs being erased after loading the conversation
This commit addresses both of them.

Gitlab: #1671
Change-Id: I67a003ea1149c27e749efffe496f4c9ce86615ea
2024-07-22 12:10:25 -04:00
78389d8c28 data transfer model: fix warning
Change-Id: Ia4fcc47c9f033a8f136d6f6de0fc4bb666a1cdfc
2024-07-18 14:52:28 -04:00
e6d820850a misc: bump daemon submodule
In addition to integrating the new UPnP code introduced into
dhtnet, this bump also includes numerous bug-fixes:
https://git.jami.net/savoirfairelinux/jami-client-qt/-/issues/1637
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1021
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1033
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1026
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/952
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1025

Change-Id: Ic7242e3dfe14550221d9d0de48ff84605b7fefd8
2024-07-16 14:09:50 -04:00
0a7f9349a9 smartlist: don't display misleading 'last interaction' date
If a conversation has no interactions (which shouldn't happen normally,
but sometimes occurs in practice), then its LastInteractionTimeStamp
will be zero, which causes the last interaction date in the smartlist to
be wrongly displayed as 31/12/1969 or 1/1/1970. This patch adds a check
to prevent this.

GitLab: #1794
Change-Id: I1384d6675c9fcaa1904bb6e1706589305b7618e9
2024-07-12 09:56:50 -04:00
99254f8d02 messagelistmodel: add support for file deletion
+ Add button to delete messages on file transfer
+ Show "Deleted media" on deleted files.
+ Update last interaction
+ Update icon for saving file, we're in 2024, no more floppy disk

Change-Id: I607b1a6beda443db85c60d8cf95a9aae29ce1f7c
GitLab: #1287
2024-07-10 16:00:39 -04:00
010a2c4eea linkdevicedialog: fix what seems to have been a copy-paste error
The "success" property of the wrong component was being set in the
"on-link-device" signal handler. This commit fixes that.

Gitlab: #1788
Change-Id: I99c9abbfa31ea9ea6e7828dbbed0a21081f8be19
2024-07-05 15:56:01 -04:00
61163037d4 misc: bump daemon submodule
This bump will include changes to fix failing builds on Windows.
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1022

Change-Id: Ic34a097fbcea5723c8fe44da9c5887368dce2258
2024-07-04 16:03:20 -04:00
3577982a93 testing: added account switcher box
Change-Id: I76b67b819cd8e028062406b96583a36ae6a6d509
2024-07-04 15:53:04 -04:00
15 changed files with 124 additions and 44 deletions

2
daemon

Submodule daemon updated: c9f251d797...51d767d982

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M42 13.85V39q0 1.2-.9 2.1-.9.9-2.1.9H9q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h25.15Zm-3 1.35L32.8 9H9v30h30ZM24 35.75q2.15 0 3.675-1.525T29.2 30.55q0-2.15-1.525-3.675T24 25.35q-2.15 0-3.675 1.525T18.8 30.55q0 2.15 1.525 3.675T24 35.75ZM11.65 18.8h17.9v-7.15h-17.9ZM9 15.2V39 9Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#e8eaed"><path d="M480-313 287-506l43-43 120 120v-371h60v371l120-120 43 43-193 193ZM220-160q-24 0-42-18t-18-42v-143h60v143h520v-143h60v143q0 24-18 42t-42 18H220Z"/></svg>

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 268 B

View File

@ -145,6 +145,16 @@ ApplicationWindow {
LRCInstance.selectConversation(convUid);
}
}
ListElement {
label: "Account ID"
type: "combobox"
getDataModel: () => AccountListModel
displayRole: AccountList.Username
onIndexChanged: function(model, index) {
const accountId = JamiQmlUtils.getModelData(model, index, AccountList.ID);
LRCInstance.currentAccountId = accountId;
}
}
ListElement {
label: "Force local preview"
type: "checkbox"

View File

@ -40,9 +40,18 @@ Loader {
property int seq: MsgSeq.single
property string author: Author
property string body: Body
property var tid: TID
property int transferStatus: TransferStatus
onTidChanged: {
if (tid === "") {
sourceComponent = deletedMsgComp
}
}
onTransferStatusChanged: {
if (transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED) {
if (tid === "") {
sourceComponent = deletedMsgComp
return;
} else if (transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED) {
mediaInfo = MessagesAdapter.getMediaInfo(root.body);
if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE) {
sourceComponent = localMediaMsgComp;
@ -58,6 +67,54 @@ Loader {
Behavior on opacity { NumberAnimation { duration: 100 } }
onLoaded: opacity = 1
Component {
id: deletedMsgComp
SBSMessageBase {
id: deletedItem
isOutgoing: Author === CurrentAccount.uri
showTime: root.showTime
seq: root.seq
author: Author
readers: Readers
timestamp: root.timestamp
formattedTime: root.formattedTime
formattedDay: root.formattedTime
extraHeight: 0
textContentWidth: textEditId.width
textContentHeight: textEditId.height
innerContent.children: [
TextEdit {
id: textEditId
anchors.right: isOutgoing ? parent.right : undefined
anchors.rightMargin: isOutgoing ? timeWidth : 0
bottomPadding: 6
topPadding: 6
leftPadding: 10
text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author) + " " + JamiStrings.deletedMedia ;
horizontalAlignment: Text.AlignLeft
width: Math.min((2 / 3) * parent.width, implicitWidth + 18, innerContent.width - senderMargin + 18)
font.pointSize: JamiTheme.smallFontSize
font.hintingPreference: Font.PreferNoHinting
renderType: Text.NativeRendering
textFormat: Text.RichText
clip: true
readOnly: true
color: getBaseColor()
opacity: 0.5
function getBaseColor() {
bubble.isDeleted = true
return UtilsAdapter.luma(bubble.color) ? "white" : "dark"
}
}
]
}
}
Component {
id: dataTransferMsgComp
@ -223,8 +280,8 @@ Loader {
: JamiTheme.chatviewTextColorDark
}
}
}
,ProgressBar {
},
ProgressBar {
id: progressBar
visible: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING

View File

@ -121,10 +121,7 @@ Item {
font.pixelSize : text.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize
property string registeredName: CurrentAccount.registeredName
property string infohash: CurrentAccount.uri
text: registeredName ? registeredName : infohash
onRegisteredNameChanged: {
text = registeredName ? registeredName : infohash
}
text: (btnId.clicked && registeredName) ? registeredName : infohash
}
}
}
@ -231,11 +228,9 @@ Item {
toolTipText: JamiStrings.identifierURI
onClicked: {
if (clicked) {
usernameLabel.text = Qt.binding(function() {return CurrentAccount.uri} );
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.uri} );
btnId.toolTipText = JamiStrings.identifierRegisterName;
} else {
usernameLabel.text = Qt.binding(function() {return CurrentAccount.registeredName} );
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.registeredName} );
btnId.toolTipText = JamiStrings.identifierURI;
}

View File

@ -382,7 +382,11 @@ Control {
property bool bubbleHovered
property string imgSource
width: (root.type === Interaction.Type.TEXT ? root.textContentWidth + (IsEmojiOnly || root.bigMsg ? 0 : root.timeWidth + root.editedWidth) : innerContent.childrenRect.width)
width: (root.type === Interaction.Type.TEXT || isDeleted ?
root.textContentWidth + (IsEmojiOnly || root.bigMsg ?
0
: root.timeWidth + root.editedWidth)
: innerContent.childrenRect.width)
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) + (root.bigMsg ? 15 : 0)
HoverHandler {

View File

@ -175,7 +175,7 @@ BaseContextMenu {
GeneralMenuItem {
id: deleteMessage
canTrigger: root.isOutgoing && type === Interaction.Type.TEXT
canTrigger: root.isOutgoing && (type === Interaction.Type.TEXT || type === Interaction.Type.DATA_TRANSFER)
iconSource: JamiResources.delete_svg
itemName: JamiStrings.deleteMessage
onClicked: {

View File

@ -125,7 +125,11 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
if (interaction.type == interaction::Type::UPDATE_PROFILE) {
lastInteractionBody = interaction::getProfileUpdatedString();
} else if (interaction.type == interaction::Type::DATA_TRANSFER) {
lastInteractionBody = interaction.commit.value("displayName");
if (interaction.commit.value("tid").isEmpty()) {
lastInteractionBody = tr("Deleted media");
} else {
lastInteractionBody = interaction.commit.value("displayName");
}
} else if (interaction.type == lrc::api::interaction::Type::CALL) {
const auto isOutgoing = interaction.authorUri == accInfo.profileInfo.uri;
lastInteractionBody = interaction::getCallInteractionString(isOutgoing, interaction);

View File

@ -88,7 +88,7 @@ Rectangle {
mirror: UtilsAdapter.isRTL
source: JamiResources.back_24dp_svg
toolTipText: CurrentConversation.inCall ? JamiStrings.backCall : JamiStrings.hideChat
toolTipText: CurrentConversation.inCall ? JamiStrings.returnToCall : JamiStrings.hideChat
onClicked: root.backClicked()
}

View File

@ -38,9 +38,9 @@ ItemDelegate {
highlighted: ListView.isCurrentItem
property bool interactive: true
property string lastInteractionDate: LastInteractionTimeStamp === undefined ? "" : LastInteractionTimeStamp
property string lastInteractionFormattedDate: MessagesAdapter.getBestFormattedDate(lastInteractionDate)
property int lastInteractionTimeStamp: LastInteractionTimeStamp
property string lastInteractionFormattedDate: MessagesAdapter.getBestFormattedDate(lastInteractionTimeStamp)
property bool showSharePositionIndicator: PositionManager.isPositionSharedToConv(accountId, UID)
property bool showSharedPositionIndicator: PositionManager.isConvSharingPosition(accountId, UID)
@ -58,7 +58,7 @@ ItemDelegate {
Connections {
target: MessagesAdapter
function onTimestampUpdated() {
lastInteractionFormattedDate = MessagesAdapter.getBestFormattedDate(lastInteractionDate);
lastInteractionFormattedDate = MessagesAdapter.getBestFormattedDate(lastInteractionTimeStamp);
}
}
@ -130,7 +130,7 @@ ItemDelegate {
color: JamiTheme.textColor
}
RowLayout {
visible: ContactType !== Profile.Type.TEMPORARY && !IsBanned && lastInteractionFormattedDate !== undefined && interactive
visible: ContactType !== Profile.Type.TEMPORARY && !IsBanned && lastInteractionTimeStamp > 0 && interactive
Layout.fillWidth: true
Layout.minimumHeight: 20
Layout.alignment: Qt.AlignTop
@ -138,7 +138,7 @@ ItemDelegate {
// last Interaction date
Text {
Layout.alignment: Qt.AlignVCenter
text: lastInteractionFormattedDate === undefined ? "" : lastInteractionFormattedDate
text: lastInteractionFormattedDate
textFormat: TextEdit.PlainText
font.pointSize: JamiTheme.smallFontSize
font.weight: UnreadMessagesCount ? Font.DemiBold : Font.Normal

View File

@ -346,7 +346,8 @@ Item {
property string disabledAccount: qsTr("The account is disabled")
property string noNetworkConnectivity: qsTr("No network connectivity")
property string deletedMessage: qsTr("deleted a message")
property string backCall: qsTr("Back to Call")
property string deletedMedia: qsTr("deleted a media")
property string returnToCall: qsTr("Return to call")
//MessagesResearch
property string jumpTo: qsTr("Jump to")

View File

@ -53,7 +53,7 @@ BaseModalDialog {
pinRectangle.visible = true
exportedPIN.text = pin;
} else {
pinRectangle.success = false;
infoLabel.success = false;
infoLabel.visible = true;
switch (status) {
case NameDirectory.ExportOnRingStatus.WRONG_PASSWORD:

View File

@ -38,7 +38,7 @@ namespace api {
class BehaviorController;
namespace datatransfer {
class Info;
struct Info;
} // namespace datatransfer
/**

View File

@ -55,6 +55,7 @@ struct Info;
X(ReplyToAuthor) \
X(TotalSize) \
X(TransferName) \
X(TID) \
X(FileExtension) \
X(Readers) \
X(IsEmojiOnly) \

View File

@ -201,16 +201,19 @@ MessageListModel::update(const QString& id, const interaction::Info& interaction
return true;
}
}
// DataTransfer interactions should not be updated.
if (current.type == interaction::Type::DATA_TRANSFER) {
return true;
// TODO: look into why this update with an empty body is broadcasted just
// after loading the messages. This is a workaround to avoid the empty
// file transfer path. Until then, don't update the body if it's empty.
if (!interaction.body.isEmpty()) {
current.body = interaction.body;
}
// Just update bodies notify the view otherwise.
current.body = interaction.body;
current.commit = interaction.commit;
current.previousBodies = interaction.previousBodies;
current.parsedBody = interaction.parsedBody;
auto modelIndex = QAbstractListModel::index(indexOfMessage(id), 0);
Q_EMIT dataChanged(modelIndex, modelIndex, {Role::Body, Role::PreviousBodies, Role::ParsedBody});
Q_EMIT dataChanged(modelIndex,
modelIndex,
{Role::TID, Role::Body, Role::PreviousBodies, Role::ParsedBody});
return true;
}
@ -251,24 +254,27 @@ MessageListModel::updateStatus(const QString& id,
bool
MessageListModel::updateTransferStatus(const QString& id,
interaction::TransferStatus newStatus,
const QString& newBody)
interaction::TransferStatus newStatus,
const QString& newBody)
{
const std::lock_guard<std::recursive_mutex> lk(mutex_);
auto it = find(id);
if (it == interactions_.end()) {
return false;
}
VectorInt roles;
if (it->second.transferStatus == newStatus) {
with(id, [&](const QString&, interaction::Info& interaction) {
if (interaction.transferStatus == newStatus) {
return;
}
interaction.transferStatus = newStatus;
roles.push_back(Role::TransferStatus);
if (!newBody.isEmpty()) {
interaction.body = newBody;
roles.push_back(Role::Body);
}
});
if (roles.empty()) {
return false;
}
it->second.transferStatus = newStatus;
roles.push_back(Role::TransferStatus);
if (!newBody.isEmpty()) {
it->second.body = newBody;
roles.push_back(Role::Body);
}
auto idx = indexOfMessage(id);
auto modelIndex = QAbstractListModel::index(idx, 0);
Q_EMIT dataChanged(modelIndex, modelIndex, roles);
return true;
}
@ -526,7 +532,7 @@ MessageListModel::dataForItem(const item_t& item, int, int role) const
auto bestName = item.second.authorUri == account_->profileInfo.uri
? account_->accountModel->bestNameForAccount(account_->id)
: account_->contactModel->bestNameForContact(
item.second.authorUri);
item.second.authorUri);
return QVariant(
interaction::getContactInteractionString(bestName,
interaction::to_action(
@ -594,6 +600,8 @@ MessageListModel::dataForItem(const item_t& item, int, int role) const
return QVariant(item.second.commit["totalSize"].toInt());
case Role::TransferName:
return QVariant(item.second.commit["displayName"]);
case Role::TID:
return QVariant(item.second.commit["tid"]);
case Role::FileExtension:
return QVariant(QFileInfo(item.second.body).suffix());
case Role::Readers: