blob: befe9ea9ff7ee17dbd9db33070de997d7b2f4963 [file] [log] [blame]
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import RxSwift
import Contacts
import SwiftyBeaver
class ContactRequestsViewModel: Stateable, ViewModel {
// MARK: - Rx Stateable
private let stateSubject = PublishSubject<State>()
lazy var state: Observable<State> = {
return self.stateSubject.asObservable()
}()
let contactsService: ContactsService
let accountsService: AccountsService
let conversationService: ConversationsService
let nameService: NameService
let presenceService: PresenceService
fileprivate let disposeBag = DisposeBag()
fileprivate let log = SwiftyBeaver.self
fileprivate let injectionBag: InjectionBag
required init(with injectionBag: InjectionBag) {
self.contactsService = injectionBag.contactsService
self.accountsService = injectionBag.accountService
self.conversationService = injectionBag.conversationsService
self.nameService = injectionBag.nameService
self.presenceService = injectionBag.presenceService
self.injectionBag = injectionBag
self.contactsService.contactRequests
.asObservable()
.subscribe(onNext: {[unowned self] contactRequests in
guard let account = self.accountsService.currentAccount else { return }
guard let ringId = contactRequests.last?.ringId else { return }
self.conversationService.generateMessage(ofType: GeneratedMessageType.receivedContactRequest,
forRindId: ringId,
forAccount: account)
})
.disposed(by: self.disposeBag)
}
lazy var contactRequestItems: Observable<[ContactRequestItem]> = {
return self.contactsService.contactRequests
.asObservable()
.map({ [unowned self] contactRequests in
return contactRequests
.filter { $0.accountId == self.accountsService.currentAccount?.id }
.sorted { $0.receivedDate > $1.receivedDate }
.map { contactRequest in
let item = ContactRequestItem(withContactRequest: contactRequest)
self.lookupUserName(withItem: item)
return item
}
})
}()
lazy var hasInvitations: Observable<Bool> = {
return self.contactsService.contactRequests
.asObservable()
.map({ items in
return !items.isEmpty
})
}()
func accept(withItem item: ContactRequestItem) -> Observable<Void> {
let acceptCompleted = self.contactsService.accept(contactRequest: item.contactRequest, withAccount: self.accountsService.currentAccount!)
let accountHelper = AccountModelHelper(withAccount: self.accountsService.currentAccount!)
self.conversationService.saveMessage(withId: "",
withContent: GeneratedMessageType.contactRequestAccepted.rawValue,
byAuthor: accountHelper.ringId!,
toConversationWith: item.contactRequest.ringId,
toAccountId: (self.accountsService.currentAccount?.id)!,
toAccountUri: accountHelper.ringId!,
generated: true,
shouldRefreshConversations: true)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message saved")
})
.disposed(by: disposeBag)
self.presenceService.subscribeBuddy(withAccountId: (self.accountsService.currentAccount?.id)!,
withUri: item.contactRequest.ringId,
withFlag: true)
if let vCard = item.contactRequest.vCard {
let saveVCardCompleted = self.contactsService.saveVCard(vCard: vCard, forContactWithRingId: item.contactRequest.ringId)
return Observable<Void>.zip(acceptCompleted, saveVCardCompleted) { _, _ in
return
}
} else {
return acceptCompleted.asObservable()
}
}
func discard(withItem item: ContactRequestItem) -> Observable<Void> {
return self.contactsService.discard(contactRequest: item.contactRequest,
withAccount: self.accountsService.currentAccount!)
}
func ban(withItem item: ContactRequestItem) -> Observable<Void> {
let discardCompleted = self.contactsService.discard(contactRequest: item.contactRequest,
withAccount: self.accountsService.currentAccount!)
let removeCompleted = self.contactsService.removeContact(withRingId: item.contactRequest.ringId,
ban: true,
withAccount: self.accountsService.currentAccount!)
return Observable<Void>.zip(discardCompleted, removeCompleted) { _, _ in
return
}
}
fileprivate func lookupUserName(withItem item: ContactRequestItem) {
self.nameService.usernameLookupStatus.asObservable()
.filter({ lookupNameResponse in
return lookupNameResponse.address == item.contactRequest.ringId
})
.subscribe(onNext: { lookupNameResponse in
if lookupNameResponse.state == .found && !lookupNameResponse.name.isEmpty {
item.userName.value = lookupNameResponse.name
} else {
item.userName.value = lookupNameResponse.address
}
})
.disposed(by: self.disposeBag)
self.nameService.lookupAddress(withAccount: (accountsService.currentAccount?.id)!,
nameserver: "",
address: item.contactRequest.ringId)
}
func showConversation (forRingId ringId: String) {
let conversationViewModel = ConversationViewModel(with: self.injectionBag)
let conversation = self.conversationService.findConversation(withRingId: ringId,
withAccountId: (accountsService.currentAccount?.id)!)
conversationViewModel.conversation = Variable<ConversationModel>(conversation!)
self.stateSubject.onNext(ConversationsState.conversationDetail(conversationViewModel: conversationViewModel))
}
}