1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-22 15:54:00 +02:00

swarm: transform non swarm to swarm conversations

+ Remove readOnly from conversation's as it was never used
and not necessary in multi swarm as you can re-add members anyway
so it's never read only.
+ Makes non swarm conversations just readable.
Users can save whatever they want and replace old non migrated
conversations to new swarm.

Change-Id: I8aa2521bc524b6159d7ba0b613834438e293e09e
This commit is contained in:
Sébastien Blin 2022-07-20 11:46:19 -04:00
parent 216f10b6de
commit 1881ffb45f
14 changed files with 38 additions and 46 deletions

View file

@ -168,7 +168,7 @@
<file>src/app/commoncomponents/BubbleLabel.qml</file> <file>src/app/commoncomponents/BubbleLabel.qml</file>
<file>src/app/commoncomponents/BackButton.qml</file> <file>src/app/commoncomponents/BackButton.qml</file>
<file>src/app/commoncomponents/JamiSwitch.qml</file> <file>src/app/commoncomponents/JamiSwitch.qml</file>
<file>src/app/mainview/components/ReadOnlyFooter.qml</file> <file>src/app/mainview/components/UpdateToSwarm.qml</file>
<file>src/app/commoncomponents/TextMessageDelegate.qml</file> <file>src/app/commoncomponents/TextMessageDelegate.qml</file>
<file>src/app/mainview/components/MessageListView.qml</file> <file>src/app/mainview/components/MessageListView.qml</file>
<file>src/app/commoncomponents/MessageBubble.qml</file> <file>src/app/commoncomponents/MessageBubble.qml</file>

View file

@ -41,8 +41,8 @@ Item {
property string contactSearchInvitations: qsTr("Search your invitations") property string contactSearchInvitations: qsTr("Search your invitations")
property string invitations: qsTr("Invitations") property string invitations: qsTr("Invitations")
property string description: qsTr("Jami is a universal communication platform, with privacy as its foundation, that relies on a free distributed network for everyone.") property string description: qsTr("Jami is a universal communication platform, with privacy as its foundation, that relies on a free distributed network for everyone.")
property string contactLeft: qsTr("You are viewing a conversation where all participants other than you have left. New interactions will not be possible.") property string updateToSwarm: qsTr("Migrating to the Swarm technology will enable syncing this conversation across multiple devices and improve reliability. The legacy conversation history will be cleared in the process.")
property string newConversation: qsTr("Start new conversation") property string migrateConversation: qsTr("Migrate conversation")
// DaemonReconnectWindow // DaemonReconnectWindow
property string reconnectWarn: qsTr("Could not re-connect to the Jami daemon (jamid).\nJami will now quit.") property string reconnectWarn: qsTr("Could not re-connect to the Jami daemon (jamid).\nJami will now quit.")

View file

@ -147,8 +147,6 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
} }
return ret; return ret;
} }
case Role::ReadOnly:
return QVariant(item.readOnly);
case Role::Presence: { case Role::Presence: {
// The conversation can show a green dot if at least one peer is present // The conversation can show a green dot if at least one peer is present
Q_FOREACH (const auto& peerUri, model_->peersForConversation(item.uid)) Q_FOREACH (const auto& peerUri, model_->peersForConversation(item.uid))

View file

@ -48,8 +48,7 @@
X(IsRequest) \ X(IsRequest) \
X(Mode) \ X(Mode) \
X(Uris) \ X(Uris) \
X(Monikers) \ X(Monikers)
X(ReadOnly)
namespace ConversationList { namespace ConversationList {
Q_NAMESPACE Q_NAMESPACE

View file

@ -438,18 +438,15 @@ ConversationsAdapter::getConvInfoMap(const QString& convId)
{"needsSyncing", convInfo.needsSyncing}, {"needsSyncing", convInfo.needsSyncing},
{"isAudioOnly", isAudioOnly}, {"isAudioOnly", isAudioOnly},
{"callState", static_cast<int>(callState)}, {"callState", static_cast<int>(callState)},
{"callStackViewShouldShow", callStackViewShouldShow}, {"callStackViewShouldShow", callStackViewShouldShow}};
{"readOnly", convInfo.readOnly}};
} }
void void
ConversationsAdapter::restartConversation(const QString& convId) ConversationsAdapter::restartConversation(const QString& convId)
{ {
// make sure this conversation meets the criteria of a "restartable" conv
// 'readOnly' implies 'isSwarm'
auto& accInfo = lrcInstance_->getCurrentAccountInfo(); auto& accInfo = lrcInstance_->getCurrentAccountInfo();
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId); const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId);
if (convInfo.uid.isEmpty() || !convInfo.isCoreDialog() || !convInfo.readOnly) { if (convInfo.uid.isEmpty() || !convInfo.isCoreDialog()) {
return; return;
} }
@ -474,7 +471,7 @@ ConversationsAdapter::restartConversation(const QString& convId)
[this, peerUri, &accInfo](const QString& convId) { [this, peerUri, &accInfo](const QString& convId) {
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId); const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId);
// 3. filter for the correct contact-conversation and select it // 3. filter for the correct contact-conversation and select it
if (!convInfo.uid.isEmpty() && convInfo.isCoreDialog() && !convInfo.readOnly if (!convInfo.uid.isEmpty() && convInfo.isCoreDialog()
&& peerUri && peerUri
== accInfo.conversationModel->peersForConversation(convId).at(0)) { == accInfo.conversationModel->peersForConversation(convId).at(0)) {
lrcInstance_->selectConversation(convId); lrcInstance_->selectConversation(convId);

View file

@ -57,7 +57,6 @@ CurrentConversation::updateData()
set_isLegacy(convInfo.isLegacy()); set_isLegacy(convInfo.isLegacy());
set_isCoreDialog(convInfo.isCoreDialog()); set_isCoreDialog(convInfo.isCoreDialog());
set_isRequest(convInfo.isRequest); set_isRequest(convInfo.isRequest);
set_readOnly(convInfo.readOnly);
set_needsSyncing(convInfo.needsSyncing); set_needsSyncing(convInfo.needsSyncing);
set_color(Utils::getAvatarColor(convId).name()); set_color(Utils::getAvatarColor(convId).name());
set_isSip(accInfo.profileInfo.type == profile::Type::SIP); set_isSip(accInfo.profileInfo.type == profile::Type::SIP);

View file

@ -37,7 +37,6 @@ class CurrentConversation final : public QObject
QML_PROPERTY(bool, isLegacy) QML_PROPERTY(bool, isLegacy)
QML_PROPERTY(bool, isCoreDialog) QML_PROPERTY(bool, isCoreDialog)
QML_PROPERTY(bool, isRequest) QML_PROPERTY(bool, isRequest)
QML_PROPERTY(bool, readOnly)
QML_PROPERTY(bool, needsSyncing) QML_PROPERTY(bool, needsSyncing)
QML_PROPERTY(bool, isSip) QML_PROPERTY(bool, isSip)
QML_PROPERTY(bool, isBanned) QML_PROPERTY(bool, isBanned)

View file

@ -160,8 +160,8 @@ Rectangle {
} }
} }
ReadOnlyFooter { UpdateToSwarm {
visible: CurrentConversation.readOnly visible: !CurrentConversation.isSwarm && !CurrentConversation.isTemporary
Layout.fillWidth: true Layout.fillWidth: true
} }
@ -171,11 +171,11 @@ Rectangle {
visible: { visible: {
if (CurrentConversation.isBlocked) if (CurrentConversation.isBlocked)
return false return false
else if (CurrentConversation.needsSyncing || CurrentConversation.readOnly) else if (CurrentConversation.needsSyncing)
return false return false
else if (CurrentConversation.isSwarm && CurrentConversation.isRequest) else if (CurrentConversation.isSwarm && CurrentConversation.isRequest)
return false return false
return true return CurrentConversation.isSwarm || CurrentConversation.isTemporary
} }
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter

View file

@ -46,12 +46,9 @@ Rectangle {
property bool interactionButtonsVisibility: { property bool interactionButtonsVisibility: {
if (CurrentConversation.inCall) if (CurrentConversation.inCall)
return false return false
if (CurrentConversation.isSwarm && if (!CurrentConversation.isTemporary && !CurrentConversation.isSwarm)
CurrentConversation.readOnly)
return false return false
if (CurrentConversation.isSwarm && if (CurrentConversation.isRequest || CurrentConversation.needsSyncing)
(CurrentConversation.isRequest ||
CurrentConversation.needsSyncing))
return false return false
return true return true
} }

View file

@ -133,7 +133,7 @@ JamiListView {
"isSwarm": model.dataForRow(row, ConversationList.IsSwarm), "isSwarm": model.dataForRow(row, ConversationList.IsSwarm),
"isBanned": model.dataForRow(row, ConversationList.IsBanned), "isBanned": model.dataForRow(row, ConversationList.IsBanned),
"mode": model.dataForRow(row, ConversationList.Mode), "mode": model.dataForRow(row, ConversationList.Mode),
"readOnly": model.dataForRow(row, ConversationList.ReadOnly) "isTemporary": model.dataForRow(row, ConversationList.ContactType) === Profile.Type.TEMPORARY,
} }
responsibleAccountId = LRCInstance.currentAccountId responsibleAccountId = LRCInstance.currentAccountId
@ -142,7 +142,7 @@ JamiListView {
isBanned = item.isBanned isBanned = item.isBanned
mode = item.mode mode = item.mode
contactType = LRCInstance.currentAccountType contactType = LRCInstance.currentAccountType
readOnly = item.readOnly readOnly = mode === Conversation.Mode.NON_SWARM && !item.isTemporary
if (model.dataForRow(row, ConversationList.IsCoreDialog)) { if (model.dataForRow(row, ConversationList.IsCoreDialog)) {
userProfile.aliasText = item.title userProfile.aliasText = item.title

View file

@ -168,13 +168,6 @@ ItemDelegate {
} }
} }
// read-only conversation indicator
ResponsiveImage {
visible: ReadOnly
source: JamiResources.lock_black_24dp_svg
color: JamiTheme.primaryForegroundColor
}
// Draft indicator // Draft indicator
ResponsiveImage { ResponsiveImage {
visible: Draft && !root.highlighted visible: Draft && !root.highlighted

View file

@ -46,7 +46,7 @@ Control {
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
text: JamiStrings.contactLeft text: JamiStrings.updateToSwarm
font.pointSize: JamiTheme.textFontSize + 2 font.pointSize: JamiTheme.textFontSize + 2
color: JamiTheme.textColor color: JamiTheme.textColor
wrapMode: Text.Wrap wrapMode: Text.Wrap
@ -60,6 +60,7 @@ Control {
MaterialButton { MaterialButton {
text: JamiStrings.removeContact text: JamiStrings.removeContact
padding: 8
autoAccelerator: true autoAccelerator: true
font.pointSize: JamiTheme.textFontSize + 2 font.pointSize: JamiTheme.textFontSize + 2
onClicked: MessagesAdapter.removeContact( onClicked: MessagesAdapter.removeContact(
@ -67,7 +68,8 @@ Control {
} }
MaterialButton { MaterialButton {
text: JamiStrings.newConversation text: JamiStrings.migrateConversation
padding: 8
autoAccelerator: true autoAccelerator: true
font.pointSize: JamiTheme.textFontSize + 2 font.pointSize: JamiTheme.textFontSize + 2
onClicked: ConversationsAdapter.restartConversation( onClicked: ConversationsAdapter.restartConversation(

View file

@ -82,13 +82,25 @@ struct Info
MapStringString infos {}; MapStringString infos {};
QString getCallId() const { return confId.isEmpty() ? callId : confId; } QString getCallId() const
{
return confId.isEmpty() ? callId : confId;
}
inline bool isLegacy() const { return mode == Mode::NON_SWARM; } inline bool isLegacy() const
inline bool isSwarm() const { return !isLegacy(); } {
return mode == Mode::NON_SWARM;
}
inline bool isSwarm() const
{
return !isLegacy();
}
// for each contact we must have one non-swarm conversation or one active one-to-one // for each contact we must have one non-swarm conversation or one active one-to-one
// conversation. Where active means peer did not leave the conversation. // conversation. Where active means peer did not leave the conversation.
inline bool isCoreDialog() const { return isLegacy() || mode == Mode::ONE_TO_ONE; }; inline bool isCoreDialog() const
{
return isLegacy() || mode == Mode::ONE_TO_ONE;
};
inline QStringList participantsUris() const inline QStringList participantsUris() const
{ {
@ -101,7 +113,6 @@ struct Info
Mode mode = Mode::NON_SWARM; Mode mode = Mode::NON_SWARM;
bool needsSyncing = false; bool needsSyncing = false;
bool isRequest = false; bool isRequest = false;
bool readOnly = false;
}; };
} // namespace conversation } // namespace conversation

View file

@ -112,10 +112,9 @@ public:
* return a vector of conversation indices for the given contact uri empty * return a vector of conversation indices for the given contact uri empty
* if no index is found * if no index is found
* @param uri of the contact to search * @param uri of the contact to search
* @param writable whether or not to exclude read-only conversations(use for interactions)
* @return an vector of indices * @return an vector of indices
*/ */
std::vector<int> getIndicesForContact(const QString& uri, bool writable = false) const; std::vector<int> getIndicesForContact(const QString& uri) const;
/** /**
* Initialize conversations_ and filteredConversations_ * Initialize conversations_ and filteredConversations_
*/ */
@ -2657,7 +2656,6 @@ ConversationModelPimpl::slotConversationMemberEvent(const QString& accountId,
membersRemaining.append(member["uri"]); membersRemaining.append(member["uri"]);
} }
conversation.participants = participants; conversation.participants = participants;
conversation.readOnly = membersRemaining == VectorString(1, linked.owner.profileInfo.uri);
invalidateModel(); invalidateModel();
Q_EMIT linked.modelChanged(); Q_EMIT linked.modelChanged();
Q_EMIT linked.conversationUpdated(conversationId); Q_EMIT linked.conversationUpdated(conversationId);
@ -2938,7 +2936,6 @@ ConversationModelPimpl::addSwarmConversation(const QString& convId)
if (member["role"] == "left") if (member["role"] == "left")
membersLeft.append(member["uri"]); membersLeft.append(member["uri"]);
} }
conversation.readOnly = mode == conversation::Mode::ONE_TO_ONE && membersLeft.size() == 1;
conversation.participants = participants; conversation.participants = participants;
conversation.mode = mode; conversation.mode = mode;
conversation.unreadMessages = ConfigurationManager::instance().countInteractions(linked.owner.id, conversation.unreadMessages = ConfigurationManager::instance().countInteractions(linked.owner.id,
@ -3097,12 +3094,12 @@ ConversationModelPimpl::getConversationForPeerUri(const QString& uri,
} }
std::vector<int> std::vector<int>
ConversationModelPimpl::getIndicesForContact(const QString& uri, bool writable) const ConversationModelPimpl::getIndicesForContact(const QString& uri) const
{ {
std::vector<int> ret; std::vector<int> ret;
for (unsigned int i = 0; i < conversations.size(); ++i) { for (unsigned int i = 0; i < conversations.size(); ++i) {
const auto& convInfo = conversations.at(i); const auto& convInfo = conversations.at(i);
if (!convInfo.isCoreDialog() || (writable && convInfo.readOnly)) { if (!convInfo.isCoreDialog()) {
continue; continue;
} }
auto peers = peersForConversation(convInfo); auto peers = peersForConversation(convInfo);