Commit e1593f20 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

smart list: remove conversation

Add remove conversation option.

Change-Id: I214a5d5ad8b50061f66df41762d61644a70c6fc4
Gitlab: #23
parent fbd59915
......@@ -41,6 +41,7 @@ internal enum Asset {
internal static let enableSpeakerphone = ImageAsset(name: "enable_speakerphone")
internal static let fallbackAvatar = ImageAsset(name: "fallback_avatar")
internal static let icContactPicture = ImageAsset(name: "ic_contact_picture")
internal static let icConversationRemove = ImageAsset(name: "ic_conversation_remove")
internal static let infoArrow = ImageAsset(name: "info_arrow")
internal static let jamiIcon = ImageAsset(name: "jamiIcon")
internal static let leftArrow = ImageAsset(name: "left_arrow")
......
......@@ -72,6 +72,8 @@ internal enum L10n {
internal static let blockAction = L10n.tr("Localizable", "actions.blockAction")
/// Cancel
internal static let cancelAction = L10n.tr("Localizable", "actions.cancelAction")
/// Clear
internal static let clearAction = L10n.tr("Localizable", "actions.clearAction")
/// Delete
internal static let deleteAction = L10n.tr("Localizable", "actions.deleteAction")
}
......@@ -97,6 +99,10 @@ internal enum L10n {
internal static let confirmBlockContact = L10n.tr("Localizable", "alerts.confirmBlockContact")
/// Block Contact
internal static let confirmBlockContactTitle = L10n.tr("Localizable", "alerts.confirmBlockContactTitle")
/// Are you sure you want to clear the conversation with this contact?
internal static let confirmClearConversation = L10n.tr("Localizable", "alerts.confirmClearConversation")
/// Clear Conversation
internal static let confirmClearConversationTitle = L10n.tr("Localizable", "alerts.confirmClearConversationTitle")
/// Are you sure you want to delete this conversation permanently?
internal static let confirmDeleteConversation = L10n.tr("Localizable", "alerts.confirmDeleteConversation")
/// Are you sure you want to delete the conversation with this contact?
......@@ -141,6 +147,8 @@ internal enum L10n {
internal static let blockContact = L10n.tr("Localizable", "contactPage.blockContact")
/// Clear Chat
internal static let clearConversation = L10n.tr("Localizable", "contactPage.clearConversation")
/// Remove Conversation
internal static let removeConversation = L10n.tr("Localizable", "contactPage.removeConversation")
/// Send Message
internal static let sendMessage = L10n.tr("Localizable", "contactPage.sendMessage")
/// Start Audio Call
......
......@@ -144,8 +144,10 @@ class ContactViewController: UIViewController, StoryboardBased, ViewModelBased {
case 2:
_ = self?.navigationController?.popViewController(animated: false)
case 3:
self?.showDeleteConversationConfirmation()
self?.showClearConversationConfirmation()
case 4:
self?.showDeleteConversationConfirmation()
case 5:
self?.showBlockContactConfirmation()
default:
break
......@@ -155,6 +157,17 @@ class ContactViewController: UIViewController, StoryboardBased, ViewModelBased {
}).disposed(by: self.disposeBag)
}
private func showClearConversationConfirmation() {
let alert = UIAlertController(title: L10n.Alerts.confirmClearConversationTitle, message: L10n.Alerts.confirmClearConversation, preferredStyle: .alert)
let deleteAction = UIAlertAction(title: L10n.Actions.clearAction, style: .destructive) { [weak self](_: UIAlertAction!) -> Void in
self?.viewModel.clearConversation()
}
let cancelAction = UIAlertAction(title: L10n.Actions.cancelAction, style: .default) { (_: UIAlertAction!) -> Void in }
alert.addAction(deleteAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
private func showDeleteConversationConfirmation() {
let alert = UIAlertController(title: L10n.Alerts.confirmDeleteConversationTitle, message: L10n.Alerts.confirmDeleteConversationFromContact, preferredStyle: .alert)
let deleteAction = UIAlertAction(title: L10n.Actions.deleteAction, style: .destructive) { [weak self](_: UIAlertAction!) -> Void in
......
......@@ -81,6 +81,7 @@ class ContactViewModel: ViewModel, Stateable {
ContactActions(title: L10n.ContactPage.startVideoCall, image: Asset.videoRunning),
ContactActions(title: L10n.ContactPage.sendMessage, image: Asset.conversationIcon),
ContactActions(title: L10n.ContactPage.clearConversation, image: Asset.clearConversation),
ContactActions(title: L10n.ContactPage.removeConversation, image: Asset.icConversationRemove),
ContactActions(title: L10n.ContactPage.blockContact, image: Asset.blockIcon)])])
}
self.contactService
......@@ -140,8 +141,14 @@ class ContactViewModel: ViewModel, Stateable {
func deleteConversation() {
self.conversationService
.deleteConversation(conversation: conversation,
keepContactInteraction: true)
.clearHistory(conversation: conversation,
keepConversation: false)
}
func clearConversation() {
self.conversationService
.clearHistory(conversation: conversation,
keepConversation: true)
}
func blockContact() {
......@@ -153,8 +160,8 @@ class ContactViewModel: ViewModel, Stateable {
removeCompleted.asObservable()
.subscribe(onCompleted: { [unowned self] in
self.conversationService
.deleteConversation(conversation: self.conversation,
keepContactInteraction: false)
.clearHistory(conversation: self.conversation,
keepConversation: false)
}).disposed(by: self.disposeBag)
}
}
......@@ -204,7 +204,7 @@ final class InteractionDataHelper {
return interactions
}
func selectInteractionsForConversationWithAccount (conversationID: Int64,
func selectConversationInteractions (conversationID: Int64,
accountProfileID: Int64) throws -> [Interaction]? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
......
......@@ -283,7 +283,9 @@ class DBManager {
}
}
func removeConversationBetween(accountUri: String, and participantUri: String, keepAddContactEvent: Bool) -> Completable {
func clearHistoryBetween(accountUri: String,
and participantUri: String,
keepConversation: Bool) -> Completable {
return Completable.create { [unowned self] completable in
do {
guard let dataBase = RingDB.instance.ringDB else {
......@@ -300,37 +302,39 @@ class DBManager {
}
guard let conversationsID = try self.getConversationsIDBetween(accountProfileID: accountProfile.id, contactProfileID: contactProfile.id, createIfNotExists: true),
!conversationsID.isEmpty else {
let conversationID = conversationsID.first else {
throw DBBridgingError.deleteConversationFailed
}
if keepAddContactEvent {
let successInteraction = self.interactionHepler
.deleteMessageAndCallInteractions(convID: conversationsID.first!)
if successInteraction {
completable(.completed)
guard let interactions = try self.interactionHepler
.selectConversationInteractions(
conversationID: conversationsID.first!,
accountProfileID: accountProfile.id) else {
throw DBBridgingError.deleteConversationFailed
}
if !interactions.isEmpty {
if !self.interactionHepler
.deleteAllIntercations(convID: conversationID) {
completable(.error(DBBridgingError.deleteConversationFailed))
}
}
if keepConversation {
completable(.completed)
} else {
let successInteraction = self.interactionHepler
.deleteAllIntercations(convID: conversationsID.first!)
if successInteraction {
let successConversations = self.conversationHelper
.deleteConversations(conversationID: conversationsID.first!)
if successConversations {
completable(.completed)
} else {
completable(.error(DBBridgingError.deleteConversationFailed))
}
let successConversations = self.conversationHelper
.deleteConversations(conversationID: conversationsID.first!)
if successConversations {
completable(.completed)
} else {
completable(.error(DBBridgingError.deleteConversationFailed))
}
// }
}
}
} catch {
completable(.error(DBBridgingError.deleteConversationFailed))
}
return Disposables.create { }
}
}
......@@ -369,22 +373,22 @@ class DBManager {
}
guard let participant =
self.filterParticipantsFor(account: accountProfile.id,
participants: participants) else {
participants: participants) else {
throw DBBridgingError.getConversationFailed
}
guard let participantProfile = try self.profileHepler.selectProfile(profileId: participant) else {
continue
}
let conversationModel = ConversationModel(withRecipientRingId: participantProfile.uri,
accountId: accountID, accountUri: accountUri)
accountId: accountID, accountUri: accountUri)
conversationModel.participantProfile = participantProfile
conversationModel.conversationId = String(conversationID)
var messages = [MessageModel]()
guard let interactions = try self.interactionHepler
.selectInteractionsForConversationWithAccount(conversationID: conversationID,
accountProfileID: accountProfile.id),
!interactions.isEmpty else {
continue
.selectConversationInteractions(
conversationID: conversationID,
accountProfileID: accountProfile.id) else {
continue
}
for interaction in interactions {
var author = accountProfile.uri
......@@ -394,7 +398,6 @@ class DBManager {
if let message = self.convertToMessage(interaction: interaction, author: author) {
messages.append(message)
}
}
conversationModel.messages = messages
conversationsToReturn.append(conversationModel)
......
......@@ -329,8 +329,9 @@ class ConversationViewModel: Stateable, ViewModel {
blockComplete.asObservable()
.subscribe(onCompleted: { [weak self] in
if let conversation = self?.conversation.value {
self?.conversationsService.deleteConversation(conversation: conversation,
keepContactInteraction: false)
self?.conversationsService
.clearHistory(conversation: conversation,
keepConversation: false)
}
}).disposed(by: self.disposeBag)
}
......
......@@ -280,7 +280,20 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
self.searchResultsTableView.isHidden = true
}
private func showDeleteConversationConfirmation(atIndex: IndexPath) {
private func showClearConversationConfirmation(atIndex: IndexPath) {
let alert = UIAlertController(title: L10n.Alerts.confirmClearConversationTitle, message: L10n.Alerts.confirmClearConversation, preferredStyle: .alert)
let deleteAction = UIAlertAction(title: L10n.Actions.clearAction, style: .destructive) { (_: UIAlertAction!) -> Void in
if let convToDelete: ConversationViewModel = try? self.conversationsTableView.rx.model(at: atIndex) {
self.viewModel.clear(conversationViewModel: convToDelete)
}
}
let cancelAction = UIAlertAction(title: L10n.Actions.cancelAction, style: .default) { (_: UIAlertAction!) -> Void in }
alert.addAction(deleteAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
private func showRemoveConversationConfirmation(atIndex: IndexPath) {
let alert = UIAlertController(title: L10n.Alerts.confirmDeleteConversationTitle, message: L10n.Alerts.confirmDeleteConversation, preferredStyle: .alert)
let deleteAction = UIAlertAction(title: L10n.Actions.deleteAction, style: .destructive) { (_: UIAlertAction!) -> Void in
if let convToDelete: ConversationViewModel = try? self.conversationsTableView.rx.model(at: atIndex) {
......@@ -323,14 +336,19 @@ extension SmartlistViewController: UITableViewDelegate {
let block = UITableViewRowAction(style: .normal, title: "Block") { _, index in
self.showBlockContactConfirmation(atIndex: index)
}
block.backgroundColor = .orange
block.backgroundColor = .red
let delete = UITableViewRowAction(style: .normal, title: "Delete") { _, index in
self.showRemoveConversationConfirmation(atIndex: index)
}
delete.backgroundColor = .orange
let delete = UITableViewRowAction(style: .normal, title: "Clear") { _, index in
self.showDeleteConversationConfirmation(atIndex: index)
let clear = UITableViewRowAction(style: .normal, title: "Clear") { _, index in
self.showClearConversationConfirmation(atIndex: index)
}
delete.backgroundColor = .red
clear.backgroundColor = .magenta
return [delete, block]
return [clear, delete, block]
}
private func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
......
......@@ -88,8 +88,7 @@ class SmartlistViewModel: Stateable, ViewModel {
return lastMessage1.receivedDate > lastMessage2.receivedDate
})
.filter({ self?.contactsService.contact(withRingId: $0.recipientRingId) != nil
|| (!$0.messages.isEmpty && (self?.contactsService.contactRequest(withRingId: $0.recipientRingId) == nil))
.filter({ self?.contactsService.contact(withRingId: $0.recipientRingId) != nil || (!$0.messages.isEmpty && (self?.contactsService.contactRequest(withRingId: $0.recipientRingId) == nil))
})
.compactMap({ conversationModel in
......@@ -230,8 +229,21 @@ class SmartlistViewModel: Stateable, ViewModel {
})) {
self.conversationsService
.deleteConversation(conversation: conversationViewModel.conversation.value,
keepContactInteraction: true)
.clearHistory(conversation: conversationViewModel.conversation.value,
keepConversation: false)
self.conversationViewModels.remove(at: index)
}
}
func clear(conversationViewModel: ConversationViewModel) {
if let index = self.conversationViewModels.index(where: ({ cvm in
cvm.conversation.value == conversationViewModel.conversation.value
})) {
self.conversationsService
.clearHistory(conversation: conversationViewModel.conversation.value,
keepConversation: true)
self.conversationViewModels.remove(at: index)
}
}
......@@ -248,8 +260,8 @@ class SmartlistViewModel: Stateable, ViewModel {
removeCompleted.asObservable()
.subscribe(onCompleted: { [weak self] in
self?.conversationsService
.deleteConversation(conversation: conversationViewModel.conversation.value,
keepContactInteraction: false)
.clearHistory(conversation: conversationViewModel.conversation.value,
keepConversation: false)
self?.conversationViewModels.remove(at: index)
}).disposed(by: self.disposeBag)
}
......
{
"images" : [
{
"idiom" : "universal",
"filename" : "delete-2.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "delete.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "delete-1.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
......@@ -101,11 +101,14 @@
"alerts.confirmDeleteConversation" = "Are you sure you want to delete this conversation permanently?";
"alerts.confirmDeleteConversationFromContact" = "Are you sure you want to delete the conversation with this contact?";
"alerts.confirmDeleteConversationTitle" = "Delete Conversation";
"alerts.confirmClearConversation" = "Are you sure you want to clear the conversation with this contact?";
"alerts.confirmClearConversationTitle" = "Clear Conversation";
//Actions
"actions.blockAction" = "Block";
"actions.deleteAction" = "Delete";
"actions.cancelAction" = "Cancel";
"actions.clearAction" = "Clear";
"alerts.incomingCallAllertTitle" = "Incoming call from ";
"alerts.incomingCallButtonAccept" = "Accept";
"alerts.incomingCallButtonIgnore" = "Ignore";
......@@ -161,6 +164,7 @@
"contactPage.sendMessage" = "Send Message";
"contactPage.clearConversation" = "Clear Chat";
"contactPage.blockContact" = "Block Contact";
"contactPage.removeConversation" = "Remove Conversation";
//DataTransfer
"dataTransfer.readableStatusCreated" = "Initializing…";
......
......@@ -305,8 +305,8 @@ class ConversationsService {
return self.dbManager.profileObservable(for: uri, createIfNotExists: false)
}
func deleteConversation(conversation: ConversationModel, keepContactInteraction: Bool) {
self.dbManager.removeConversationBetween(accountUri: conversation.accountUri, and: conversation.recipientRingId, keepAddContactEvent: keepContactInteraction)
func clearHistory(conversation: ConversationModel, keepConversation: Bool) {
self.dbManager.clearHistoryBetween(accountUri: conversation.accountUri, and: conversation.recipientRingId, keepConversation: keepConversation)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.subscribe(onCompleted: { [weak self] in
self?.removeSavedFiles(accountId: conversation.accountId, conversationId: conversation.conversationId)
......
......@@ -113,7 +113,7 @@ class GeneratedInteractionsManager {
if !messagesNotGenerated.isEmpty {
return
}
self.conversationService.deleteConversation(conversation: conversation, keepContactInteraction: false)
self.conversationService.clearHistory(conversation: conversation, keepConversation: false)
}
// swiftlint:disable cyclomatic_complexity
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment