diff --git a/qml.qrc b/qml.qrc index 42a243ac2425ff5d47cb56db02690fefd6f7e07c..e7ab3be111f6ad209f5213b9d062f3f81fc0ce84 100644 --- a/qml.qrc +++ b/qml.qrc @@ -168,7 +168,7 @@ <file>src/app/commoncomponents/BubbleLabel.qml</file> <file>src/app/commoncomponents/BackButton.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/mainview/components/MessageListView.qml</file> <file>src/app/commoncomponents/MessageBubble.qml</file> diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml index ad830bc83e8c4731e2c7eee0266a4dda7ea8d82e..9169e96729a4b481f63483bd9e17fb008162d10b 100644 --- a/src/app/constant/JamiStrings.qml +++ b/src/app/constant/JamiStrings.qml @@ -41,8 +41,8 @@ Item { property string contactSearchInvitations: qsTr("Search your 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 contactLeft: qsTr("You are viewing a conversation where all participants other than you have left. New interactions will not be possible.") - property string newConversation: qsTr("Start new conversation") + 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 migrateConversation: qsTr("Migrate conversation") // DaemonReconnectWindow property string reconnectWarn: qsTr("Could not re-connect to the Jami daemon (jamid).\nJami will now quit.") diff --git a/src/app/conversationlistmodelbase.cpp b/src/app/conversationlistmodelbase.cpp index 13d69e04f1996a4d892b3dda7dc0f8781274123f..827c84bd94e12f6143288bb2fec33fe480d65003 100644 --- a/src/app/conversationlistmodelbase.cpp +++ b/src/app/conversationlistmodelbase.cpp @@ -147,8 +147,6 @@ ConversationListModelBase::dataForItem(item_t item, int role) const } return ret; } - case Role::ReadOnly: - return QVariant(item.readOnly); case Role::Presence: { // The conversation can show a green dot if at least one peer is present Q_FOREACH (const auto& peerUri, model_->peersForConversation(item.uid)) diff --git a/src/app/conversationlistmodelbase.h b/src/app/conversationlistmodelbase.h index 37a2300e4aa0263b47526ad9015686da0a684678..f22e1c923ecc91e0d562c96aac93d70c91f65d5c 100644 --- a/src/app/conversationlistmodelbase.h +++ b/src/app/conversationlistmodelbase.h @@ -48,8 +48,7 @@ X(IsRequest) \ X(Mode) \ X(Uris) \ - X(Monikers) \ - X(ReadOnly) + X(Monikers) namespace ConversationList { Q_NAMESPACE diff --git a/src/app/conversationsadapter.cpp b/src/app/conversationsadapter.cpp index de792930b7befeba39a3d85bc7138eeb19eec244..5a50608d13f122d971dfdfa20afbf28c1c836205 100644 --- a/src/app/conversationsadapter.cpp +++ b/src/app/conversationsadapter.cpp @@ -438,18 +438,15 @@ ConversationsAdapter::getConvInfoMap(const QString& convId) {"needsSyncing", convInfo.needsSyncing}, {"isAudioOnly", isAudioOnly}, {"callState", static_cast<int>(callState)}, - {"callStackViewShouldShow", callStackViewShouldShow}, - {"readOnly", convInfo.readOnly}}; + {"callStackViewShouldShow", callStackViewShouldShow}}; } void ConversationsAdapter::restartConversation(const QString& convId) { - // make sure this conversation meets the criteria of a "restartable" conv - // 'readOnly' implies 'isSwarm' auto& accInfo = lrcInstance_->getCurrentAccountInfo(); const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId); - if (convInfo.uid.isEmpty() || !convInfo.isCoreDialog() || !convInfo.readOnly) { + if (convInfo.uid.isEmpty() || !convInfo.isCoreDialog()) { return; } @@ -474,7 +471,7 @@ ConversationsAdapter::restartConversation(const QString& convId) [this, peerUri, &accInfo](const QString& convId) { const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId); // 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 == accInfo.conversationModel->peersForConversation(convId).at(0)) { lrcInstance_->selectConversation(convId); diff --git a/src/app/currentconversation.cpp b/src/app/currentconversation.cpp index b27f9797054d8fddbb3286d9ff55ba2c6103cacd..1ccda9c03981339703f1db583f753c4e0b45c25c 100644 --- a/src/app/currentconversation.cpp +++ b/src/app/currentconversation.cpp @@ -57,7 +57,6 @@ CurrentConversation::updateData() set_isLegacy(convInfo.isLegacy()); set_isCoreDialog(convInfo.isCoreDialog()); set_isRequest(convInfo.isRequest); - set_readOnly(convInfo.readOnly); set_needsSyncing(convInfo.needsSyncing); set_color(Utils::getAvatarColor(convId).name()); set_isSip(accInfo.profileInfo.type == profile::Type::SIP); diff --git a/src/app/currentconversation.h b/src/app/currentconversation.h index 997317959cab1dc3b718b95ed623df1ef36c9c83..72de66eda5c1c48b9d329d115b17df86862f737b 100644 --- a/src/app/currentconversation.h +++ b/src/app/currentconversation.h @@ -37,7 +37,6 @@ class CurrentConversation final : public QObject QML_PROPERTY(bool, isLegacy) QML_PROPERTY(bool, isCoreDialog) QML_PROPERTY(bool, isRequest) - QML_PROPERTY(bool, readOnly) QML_PROPERTY(bool, needsSyncing) QML_PROPERTY(bool, isSip) QML_PROPERTY(bool, isBanned) diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index 3159a74ce26a83679b57da47b85a59f74ad0c3f6..ce29207622255d1fbf17365089feb3b8ce1e7838 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -160,8 +160,8 @@ Rectangle { } } - ReadOnlyFooter { - visible: CurrentConversation.readOnly + UpdateToSwarm { + visible: !CurrentConversation.isSwarm && !CurrentConversation.isTemporary Layout.fillWidth: true } @@ -171,11 +171,11 @@ Rectangle { visible: { if (CurrentConversation.isBlocked) return false - else if (CurrentConversation.needsSyncing || CurrentConversation.readOnly) + else if (CurrentConversation.needsSyncing) return false else if (CurrentConversation.isSwarm && CurrentConversation.isRequest) return false - return true + return CurrentConversation.isSwarm || CurrentConversation.isTemporary } Layout.alignment: Qt.AlignHCenter diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index c63d39bb26f8eeca0d6f83422f3ee961021486a0..9c0f9d9f3923e5e82cbde6a61e404f9485c2730f 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -46,12 +46,9 @@ Rectangle { property bool interactionButtonsVisibility: { if (CurrentConversation.inCall) return false - if (CurrentConversation.isSwarm && - CurrentConversation.readOnly) + if (!CurrentConversation.isTemporary && !CurrentConversation.isSwarm) return false - if (CurrentConversation.isSwarm && - (CurrentConversation.isRequest || - CurrentConversation.needsSyncing)) + if (CurrentConversation.isRequest || CurrentConversation.needsSyncing) return false return true } diff --git a/src/app/mainview/components/ConversationListView.qml b/src/app/mainview/components/ConversationListView.qml index b2eeac5c9a16d3bfa3ca447b61b4481a64814ba9..6433a9bf975bb07fc886c427fdb3272ec540a75d 100644 --- a/src/app/mainview/components/ConversationListView.qml +++ b/src/app/mainview/components/ConversationListView.qml @@ -133,7 +133,7 @@ JamiListView { "isSwarm": model.dataForRow(row, ConversationList.IsSwarm), "isBanned": model.dataForRow(row, ConversationList.IsBanned), "mode": model.dataForRow(row, ConversationList.Mode), - "readOnly": model.dataForRow(row, ConversationList.ReadOnly) + "isTemporary": model.dataForRow(row, ConversationList.ContactType) === Profile.Type.TEMPORARY, } responsibleAccountId = LRCInstance.currentAccountId @@ -142,7 +142,7 @@ JamiListView { isBanned = item.isBanned mode = item.mode contactType = LRCInstance.currentAccountType - readOnly = item.readOnly + readOnly = mode === Conversation.Mode.NON_SWARM && !item.isTemporary if (model.dataForRow(row, ConversationList.IsCoreDialog)) { userProfile.aliasText = item.title diff --git a/src/app/mainview/components/SmartListItemDelegate.qml b/src/app/mainview/components/SmartListItemDelegate.qml index 39b657317580f6442daba529555749bd550a0305..56361058788fb57016b1ea2218b0e075f563094d 100644 --- a/src/app/mainview/components/SmartListItemDelegate.qml +++ b/src/app/mainview/components/SmartListItemDelegate.qml @@ -168,13 +168,6 @@ ItemDelegate { } } - // read-only conversation indicator - ResponsiveImage { - visible: ReadOnly - source: JamiResources.lock_black_24dp_svg - color: JamiTheme.primaryForegroundColor - } - // Draft indicator ResponsiveImage { visible: Draft && !root.highlighted diff --git a/src/app/mainview/components/ReadOnlyFooter.qml b/src/app/mainview/components/UpdateToSwarm.qml similarity index 93% rename from src/app/mainview/components/ReadOnlyFooter.qml rename to src/app/mainview/components/UpdateToSwarm.qml index e639dfb5e0f3de0bd33f2fb037dda8a4e189e1b6..d43b0cc3825fccdb134a03aa5673d79ade4365e7 100644 --- a/src/app/mainview/components/ReadOnlyFooter.qml +++ b/src/app/mainview/components/UpdateToSwarm.qml @@ -46,7 +46,7 @@ Control { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.fillWidth: true - text: JamiStrings.contactLeft + text: JamiStrings.updateToSwarm font.pointSize: JamiTheme.textFontSize + 2 color: JamiTheme.textColor wrapMode: Text.Wrap @@ -60,6 +60,7 @@ Control { MaterialButton { text: JamiStrings.removeContact + padding: 8 autoAccelerator: true font.pointSize: JamiTheme.textFontSize + 2 onClicked: MessagesAdapter.removeContact( @@ -67,7 +68,8 @@ Control { } MaterialButton { - text: JamiStrings.newConversation + text: JamiStrings.migrateConversation + padding: 8 autoAccelerator: true font.pointSize: JamiTheme.textFontSize + 2 onClicked: ConversationsAdapter.restartConversation( diff --git a/src/libclient/api/conversation.h b/src/libclient/api/conversation.h index 4608b2017bcf27c911c1d91ea9666a7481269975..086fe5ff91102e92a90b128bac1e6908ca95bded 100644 --- a/src/libclient/api/conversation.h +++ b/src/libclient/api/conversation.h @@ -82,13 +82,25 @@ struct Info 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 isSwarm() const { return !isLegacy(); } + inline bool isLegacy() const + { + 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 // 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 { @@ -101,7 +113,6 @@ struct Info Mode mode = Mode::NON_SWARM; bool needsSyncing = false; bool isRequest = false; - bool readOnly = false; }; } // namespace conversation diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp index 1cacfaf7ec239d25c5dd82febc0d092d7d811cdb..89a0bc4c83302d60174fbd8345b5a3f98fdfa3ed 100644 --- a/src/libclient/conversationmodel.cpp +++ b/src/libclient/conversationmodel.cpp @@ -112,10 +112,9 @@ public: * return a vector of conversation indices for the given contact uri empty * if no index is found * @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 */ - std::vector<int> getIndicesForContact(const QString& uri, bool writable = false) const; + std::vector<int> getIndicesForContact(const QString& uri) const; /** * Initialize conversations_ and filteredConversations_ */ @@ -2657,7 +2656,6 @@ ConversationModelPimpl::slotConversationMemberEvent(const QString& accountId, membersRemaining.append(member["uri"]); } conversation.participants = participants; - conversation.readOnly = membersRemaining == VectorString(1, linked.owner.profileInfo.uri); invalidateModel(); Q_EMIT linked.modelChanged(); Q_EMIT linked.conversationUpdated(conversationId); @@ -2938,7 +2936,6 @@ ConversationModelPimpl::addSwarmConversation(const QString& convId) if (member["role"] == "left") membersLeft.append(member["uri"]); } - conversation.readOnly = mode == conversation::Mode::ONE_TO_ONE && membersLeft.size() == 1; conversation.participants = participants; conversation.mode = mode; conversation.unreadMessages = ConfigurationManager::instance().countInteractions(linked.owner.id, @@ -3097,12 +3094,12 @@ ConversationModelPimpl::getConversationForPeerUri(const QString& uri, } std::vector<int> -ConversationModelPimpl::getIndicesForContact(const QString& uri, bool writable) const +ConversationModelPimpl::getIndicesForContact(const QString& uri) const { std::vector<int> ret; for (unsigned int i = 0; i < conversations.size(); ++i) { const auto& convInfo = conversations.at(i); - if (!convInfo.isCoreDialog() || (writable && convInfo.readOnly)) { + if (!convInfo.isCoreDialog()) { continue; } auto peers = peersForConversation(convInfo);