|
@@ -1,69 +1,110 @@
|
|
|
import UIKit
|
|
|
|
|
|
-class ChatListController: UIViewController {
|
|
|
+class ChatListController: UITableViewController {
|
|
|
weak var coordinator: ChatListCoordinator?
|
|
|
+ let viewModel: ChatListViewModelProtocol
|
|
|
|
|
|
- private var dcContext: DcContext
|
|
|
- private var chatList: DcChatlist?
|
|
|
- private let showArchive: Bool
|
|
|
-
|
|
|
- private lazy var chatTable: UITableView = {
|
|
|
- let chatTable = UITableView()
|
|
|
- chatTable.dataSource = self
|
|
|
- chatTable.delegate = self
|
|
|
- chatTable.rowHeight = 80
|
|
|
- return chatTable
|
|
|
- }()
|
|
|
+ private let chatCellReuseIdentifier = "chat_cell"
|
|
|
+ private let deadDropCellReuseIdentifier = "deaddrop_cell"
|
|
|
+ private let contactCellReuseIdentifier = "contact_cell"
|
|
|
|
|
|
private var msgChangedObserver: Any?
|
|
|
private var incomingMsgObserver: Any?
|
|
|
private var viewChatObserver: Any?
|
|
|
private var deleteChatObserver: Any?
|
|
|
|
|
|
- private var newButton: UIBarButtonItem!
|
|
|
+ private lazy var searchController: UISearchController = {
|
|
|
+ let searchController = UISearchController(searchResultsController: nil)
|
|
|
+ searchController.searchResultsUpdater = viewModel
|
|
|
+ searchController.obscuresBackgroundDuringPresentation = false
|
|
|
+ searchController.searchBar.placeholder = String.localized("search")
|
|
|
+ searchController.searchBar.delegate = self
|
|
|
+ return searchController
|
|
|
+ }()
|
|
|
|
|
|
- lazy var cancelButton: UIBarButtonItem = {
|
|
|
+ private lazy var newButton: UIBarButtonItem = {
|
|
|
+ let button = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.compose, target: self, action: #selector(didPressNewChat))
|
|
|
+ button.tintColor = DcColors.primary
|
|
|
+ return button
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var cancelButton: UIBarButtonItem = {
|
|
|
let button = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed))
|
|
|
return button
|
|
|
}()
|
|
|
|
|
|
- init(dcContext: DcContext, showArchive: Bool) {
|
|
|
- self.dcContext = dcContext
|
|
|
- self.showArchive = showArchive
|
|
|
- dcContext.updateDeviceChats()
|
|
|
- super.init(nibName: nil, bundle: nil)
|
|
|
+ func getArchiveCell(title: String) -> UITableViewCell {
|
|
|
+ let cell = UITableViewCell()
|
|
|
+ cell.textLabel?.textColor = .systemBlue
|
|
|
+ cell.textLabel?.text = title
|
|
|
+ cell.textLabel?.textAlignment = .center
|
|
|
+ return cell
|
|
|
+ }
|
|
|
+
|
|
|
+ init(viewModel: ChatListViewModelProtocol) {
|
|
|
+ self.viewModel = viewModel
|
|
|
+ if viewModel.isArchive {
|
|
|
+ super.init(nibName: nil, bundle: nil)
|
|
|
+ } else {
|
|
|
+ super.init(style: .grouped)
|
|
|
+ }
|
|
|
+ viewModel.onChatListUpdate = handleChatListUpdate // register listener
|
|
|
}
|
|
|
|
|
|
required init?(coder _: NSCoder) {
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
}
|
|
|
|
|
|
+ // MARK: - lifecycle
|
|
|
+ override func viewDidLoad() {
|
|
|
+ super.viewDidLoad()
|
|
|
+ navigationItem.rightBarButtonItem = newButton
|
|
|
+ if !viewModel.isArchive {
|
|
|
+ navigationItem.searchController = searchController
|
|
|
+ }
|
|
|
+ configureTableView()
|
|
|
+ }
|
|
|
+
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
|
super.viewWillAppear(animated)
|
|
|
- getChatList()
|
|
|
+
|
|
|
updateTitle()
|
|
|
+ viewModel.refreshData()
|
|
|
+
|
|
|
+ if RelayHelper.sharedInstance.isForwarding() {
|
|
|
+ tableView.scrollToTop()
|
|
|
+ }
|
|
|
|
|
|
let nc = NotificationCenter.default
|
|
|
- msgChangedObserver = nc.addObserver(forName: dcNotificationChanged,
|
|
|
- object: nil, queue: nil) { _ in
|
|
|
- self.getChatList()
|
|
|
- }
|
|
|
- incomingMsgObserver = nc.addObserver(forName: dcNotificationIncoming,
|
|
|
- object: nil, queue: nil) { _ in
|
|
|
- self.getChatList()
|
|
|
- }
|
|
|
-
|
|
|
- viewChatObserver = nc.addObserver(forName: dcNotificationViewChat, object: nil, queue: nil) { notification in
|
|
|
- if let chatId = notification.userInfo?["chat_id"] as? Int {
|
|
|
- self.coordinator?.showChat(chatId: chatId)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- deleteChatObserver = nc.addObserver(forName: dcNotificationChatDeletedInChatDetail, object: nil, queue: nil) { notification in
|
|
|
- if let chatId = notification.userInfo?["chat_id"] as? Int {
|
|
|
- self.deleteChat(chatId: chatId, animated: true)
|
|
|
- }
|
|
|
- }
|
|
|
+ msgChangedObserver = nc.addObserver(
|
|
|
+ forName: dcNotificationChanged,
|
|
|
+ object: nil,
|
|
|
+ queue: nil) { _ in
|
|
|
+ self.viewModel.refreshData()
|
|
|
+
|
|
|
+ }
|
|
|
+ incomingMsgObserver = nc.addObserver(
|
|
|
+ forName: dcNotificationIncoming,
|
|
|
+ object: nil,
|
|
|
+ queue: nil) { _ in
|
|
|
+ self.viewModel.refreshData()
|
|
|
+ }
|
|
|
+ viewChatObserver = nc.addObserver(
|
|
|
+ forName: dcNotificationViewChat,
|
|
|
+ object: nil,
|
|
|
+ queue: nil) { notification in
|
|
|
+ if let chatId = notification.userInfo?["chat_id"] as? Int {
|
|
|
+ self.coordinator?.showChat(chatId: chatId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ deleteChatObserver = nc.addObserver(
|
|
|
+ forName: dcNotificationChatDeletedInChatDetail,
|
|
|
+ object: nil,
|
|
|
+ queue: nil) { notification in
|
|
|
+ if let chatId = notification.userInfo?["chat_id"] as? Int {
|
|
|
+ self.deleteChat(chatId: chatId, animated: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
override func viewDidDisappear(_ animated: Bool) {
|
|
@@ -85,216 +126,150 @@ class ChatListController: UIViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- override func viewDidLoad() {
|
|
|
- super.viewDidLoad()
|
|
|
-
|
|
|
- newButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.compose, target: self, action: #selector(didPressNewChat))
|
|
|
- newButton.tintColor = DcColors.primary
|
|
|
- navigationItem.rightBarButtonItem = newButton
|
|
|
-
|
|
|
- setupChatTable()
|
|
|
- }
|
|
|
-
|
|
|
- private func setupChatTable() {
|
|
|
- view.addSubview(chatTable)
|
|
|
- chatTable.translatesAutoresizingMaskIntoConstraints = false
|
|
|
- chatTable.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
|
|
- chatTable.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
|
|
- chatTable.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
|
|
- chatTable.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
|
|
+ // MARK: - configuration
|
|
|
+ private func configureTableView() {
|
|
|
+ tableView.register(ContactCell.self, forCellReuseIdentifier: chatCellReuseIdentifier)
|
|
|
+ tableView.register(ContactCell.self, forCellReuseIdentifier: deadDropCellReuseIdentifier)
|
|
|
+ tableView.register(ContactCell.self, forCellReuseIdentifier: contactCellReuseIdentifier)
|
|
|
+ tableView.rowHeight = 80
|
|
|
}
|
|
|
|
|
|
+ // MARK: - actions
|
|
|
@objc func didPressNewChat() {
|
|
|
coordinator?.showNewChatController()
|
|
|
}
|
|
|
|
|
|
@objc func cancelButtonPressed() {
|
|
|
+ // cancel forwarding
|
|
|
RelayHelper.sharedInstance.cancel()
|
|
|
+ viewModel.refreshData()
|
|
|
updateTitle()
|
|
|
}
|
|
|
|
|
|
- private func getNumberOfArchivedChats() -> Int {
|
|
|
- let chatList = dcContext.getChatlist(flags: DC_GCL_ARCHIVED_ONLY, queryString: nil, queryId: 0)
|
|
|
- return chatList.length
|
|
|
+ override func numberOfSections(in tableView: UITableView) -> Int {
|
|
|
+ return viewModel.numberOfSections
|
|
|
}
|
|
|
|
|
|
- private func getChatList() {
|
|
|
- var gclFlags: Int32 = 0
|
|
|
- if showArchive {
|
|
|
- gclFlags |= DC_GCL_ARCHIVED_ONLY
|
|
|
- }
|
|
|
- chatList = dcContext.getChatlist(flags: gclFlags, queryString: nil, queryId: 0)
|
|
|
- chatTable.reloadData()
|
|
|
- }
|
|
|
-
|
|
|
- private func updateTitle() {
|
|
|
- if RelayHelper.sharedInstance.isForwarding() {
|
|
|
- title = String.localized("forward_to")
|
|
|
- if !showArchive {
|
|
|
- navigationItem.setLeftBarButton(cancelButton, animated: true)
|
|
|
- }
|
|
|
- } else {
|
|
|
- title = showArchive ? String.localized("chat_archived_chats_title") :
|
|
|
- String.localized("pref_chats")
|
|
|
- navigationItem.setLeftBarButton(nil, animated: true)
|
|
|
- }
|
|
|
+ override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
+ return viewModel.numberOfRowsIn(section: section)
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-extension ChatListController: UITableViewDataSource, UITableViewDelegate {
|
|
|
- func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
|
|
|
- guard let chatList = self.chatList else {
|
|
|
- fatalError("chatList was nil in data source")
|
|
|
- }
|
|
|
|
|
|
- return chatList.length
|
|
|
- }
|
|
|
+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
|
|
|
|
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
|
- let row = indexPath.row
|
|
|
- guard let chatList = self.chatList else {
|
|
|
- fatalError("chatList was nil in data source")
|
|
|
- }
|
|
|
+ let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
|
|
|
|
|
|
- let chatId = chatList.getChatId(index: row)
|
|
|
- if chatId == DC_CHAT_ID_ARCHIVED_LINK {
|
|
|
- return getArchiveCell(tableView)
|
|
|
+ switch cellData.type {
|
|
|
+ case .deaddrop(let deaddropData):
|
|
|
+ guard let deaddropCell = tableView.dequeueReusableCell(withIdentifier: deadDropCellReuseIdentifier, for: indexPath) as? ContactCell else {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ deaddropCell.updateCell(cellViewModel: cellData)
|
|
|
+ return deaddropCell
|
|
|
+ case .chat(let chatData):
|
|
|
+ let chatId = chatData.chatId
|
|
|
+ if chatId == DC_CHAT_ID_ARCHIVED_LINK {
|
|
|
+ return getArchiveCell(title: DcChat(id: chatId).name)
|
|
|
+ } else if let chatCell = tableView.dequeueReusableCell(withIdentifier: chatCellReuseIdentifier, for: indexPath) as? ContactCell {
|
|
|
+ // default chatCell
|
|
|
+ chatCell.updateCell(cellViewModel: cellData)
|
|
|
+ return chatCell
|
|
|
+ }
|
|
|
+ case .contact:
|
|
|
+ safe_assert(viewModel.searchActive)
|
|
|
+ if let contactCell = tableView.dequeueReusableCell(withIdentifier: contactCellReuseIdentifier, for: indexPath) as? ContactCell {
|
|
|
+ contactCell.updateCell(cellViewModel: cellData)
|
|
|
+ return contactCell
|
|
|
+ }
|
|
|
}
|
|
|
+ safe_fatalError("Could not find/dequeue or recycle UITableViewCell.")
|
|
|
+ return UITableViewCell()
|
|
|
+ }
|
|
|
|
|
|
- let cell: ContactCell
|
|
|
- if chatId == DC_CHAT_ID_DEADDROP {
|
|
|
- cell = getDeaddropCell(tableView)
|
|
|
- } else if let c = tableView.dequeueReusableCell(withIdentifier: "ChatCell") as? ContactCell {
|
|
|
- cell = c
|
|
|
- } else {
|
|
|
- cell = ContactCell(style: .default, reuseIdentifier: "ChatCell")
|
|
|
- }
|
|
|
+ override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
|
|
+ return viewModel.titleForHeaderIn(section: section)
|
|
|
+ }
|
|
|
|
|
|
- let chat = DcChat(id: chatId)
|
|
|
- let summary = chatList.getSummary(index: row)
|
|
|
- let unreadMessages = dcContext.getUnreadMessages(chatId: chatId)
|
|
|
-
|
|
|
- cell.titleLabel.attributedText = (unreadMessages > 0) ?
|
|
|
- NSAttributedString(string: chat.name, attributes: [ .font: UIFont.systemFont(ofSize: 16, weight: .bold) ]) :
|
|
|
- NSAttributedString(string: chat.name, attributes: [ .font: UIFont.systemFont(ofSize: 16, weight: .medium) ])
|
|
|
-
|
|
|
- if chatId == DC_CHAT_ID_DEADDROP {
|
|
|
- let contact = DcContact(id: DcMsg(id: chatList.getMsgId(index: row)).fromContactId)
|
|
|
- if let img = contact.profileImage {
|
|
|
- cell.resetBackupImage()
|
|
|
- cell.setImage(img)
|
|
|
+ override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
|
+ let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
|
|
|
+ switch cellData.type {
|
|
|
+ case .deaddrop(let deaddropData):
|
|
|
+ safe_assert(deaddropData.chatId == DC_CHAT_ID_DEADDROP)
|
|
|
+ showDeaddropRequestAlert(msgId: deaddropData.msgId)
|
|
|
+ case .chat(let chatData):
|
|
|
+ let chatId = chatData.chatId
|
|
|
+ if chatId == DC_CHAT_ID_ARCHIVED_LINK {
|
|
|
+ coordinator?.showArchive()
|
|
|
} else {
|
|
|
- cell.setBackupImage(name: contact.name, color: contact.color)
|
|
|
+ coordinator?.showChat(chatId: chatId)
|
|
|
}
|
|
|
- } else {
|
|
|
- if let img = chat.profileImage {
|
|
|
- cell.resetBackupImage()
|
|
|
- cell.setImage(img)
|
|
|
+ case .contact(let contactData):
|
|
|
+ let contactId = contactData.contactId
|
|
|
+ if let chatId = contactData.chatId {
|
|
|
+ coordinator?.showChat(chatId: chatId)
|
|
|
} else {
|
|
|
- cell.setBackupImage(name: chat.name, color: chat.color)
|
|
|
+ self.askToChatWith(contactId: contactId)
|
|
|
}
|
|
|
-
|
|
|
- if chat.visibility == DC_CHAT_VISIBILITY_PINNED {
|
|
|
- cell.backgroundColor = DcColors.deaddropBackground
|
|
|
- cell.contentView.backgroundColor = DcColors.deaddropBackground
|
|
|
- } else {
|
|
|
- cell.backgroundColor = DcColors.contactCellBackgroundColor
|
|
|
- cell.contentView.backgroundColor = DcColors.contactCellBackgroundColor
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- cell.setVerified(isVerified: chat.isVerified)
|
|
|
-
|
|
|
- let result1 = summary.text1 ?? ""
|
|
|
- let result2 = summary.text2 ?? ""
|
|
|
- let result: String
|
|
|
- if !result1.isEmpty, !result2.isEmpty {
|
|
|
- result = "\(result1): \(result2)"
|
|
|
- } else {
|
|
|
- result = "\(result1)\(result2)"
|
|
|
}
|
|
|
-
|
|
|
- cell.subtitleLabel.text = result
|
|
|
- cell.setTimeLabel(summary.timestamp)
|
|
|
- cell.setStatusIndicators(unreadCount: unreadMessages, status: summary.state, visibility: chat.visibility)
|
|
|
- return cell
|
|
|
}
|
|
|
|
|
|
- func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
|
- let row = indexPath.row
|
|
|
- guard let chatList = chatList else { return }
|
|
|
- let chatId = chatList.getChatId(index: row)
|
|
|
- if chatId == DC_CHAT_ID_DEADDROP {
|
|
|
- let msgId = chatList.getMsgId(index: row)
|
|
|
- let dcMsg = DcMsg(id: msgId)
|
|
|
- let dcContact = DcContact(id: dcMsg.fromContactId)
|
|
|
- let title = String.localizedStringWithFormat(String.localized("ask_start_chat_with"), dcContact.nameNAddr)
|
|
|
- let alert = UIAlertController(title: title, message: nil, preferredStyle: .safeActionSheet)
|
|
|
- alert.addAction(UIAlertAction(title: String.localized("start_chat"), style: .default, handler: { _ in
|
|
|
- let chat = dcMsg.createChat()
|
|
|
- self.coordinator?.showChat(chatId: chat.id)
|
|
|
- }))
|
|
|
- alert.addAction(UIAlertAction(title: String.localized("not_now"), style: .default, handler: { _ in
|
|
|
- dcContact.marknoticed()
|
|
|
- }))
|
|
|
- alert.addAction(UIAlertAction(title: String.localized("menu_block_contact"), style: .destructive, handler: { _ in
|
|
|
- dcContact.block()
|
|
|
- }))
|
|
|
- alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel))
|
|
|
- present(alert, animated: true, completion: nil)
|
|
|
- } else if chatId == DC_CHAT_ID_ARCHIVED_LINK {
|
|
|
- coordinator?.showArchive()
|
|
|
- } else {
|
|
|
- coordinator?.showChat(chatId: chatId)
|
|
|
+ override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
|
|
+
|
|
|
+ if viewModel.searchActive {
|
|
|
+ // no swipe actions during search
|
|
|
+ return []
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
|
|
- let row = indexPath.row
|
|
|
- guard let chatList = chatList else {
|
|
|
+ guard let chatId = viewModel.chatIdFor(section: indexPath.section, row: indexPath.row) else {
|
|
|
return []
|
|
|
}
|
|
|
|
|
|
- let chatId = chatList.getChatId(index: row)
|
|
|
if chatId==DC_CHAT_ID_ARCHIVED_LINK || chatId==DC_CHAT_ID_DEADDROP {
|
|
|
return []
|
|
|
// returning nil may result in a default delete action,
|
|
|
// see https://forums.developer.apple.com/thread/115030
|
|
|
}
|
|
|
+ let archiveActionTitle: String = String.localized(viewModel.isArchive ? "unarchive" : "archive")
|
|
|
|
|
|
- let archive = UITableViewRowAction(style: .destructive, title: String.localized(showArchive ? "unarchive" : "archive")) { [unowned self] _, _ in
|
|
|
- self.dcContext.archiveChat(chatId: chatId, archive: !self.showArchive)
|
|
|
+ let archiveAction = UITableViewRowAction(style: .destructive, title: archiveActionTitle) { [unowned self] _, _ in
|
|
|
+ self.viewModel.archiveChatToggle(chatId: chatId)
|
|
|
}
|
|
|
- archive.backgroundColor = UIColor.lightGray
|
|
|
+ archiveAction.backgroundColor = UIColor.lightGray
|
|
|
|
|
|
- let chat = dcContext.getChat(chatId: chatId)
|
|
|
+ let chat = DcChat(id: chatId)
|
|
|
let pinned = chat.visibility==DC_CHAT_VISIBILITY_PINNED
|
|
|
- let pin = UITableViewRowAction(style: .destructive, title: String.localized(pinned ? "unpin" : "pin")) { [unowned self] _, _ in
|
|
|
- self.dcContext.setChatVisibility(chatId: chatId, visibility: pinned ? DC_CHAT_VISIBILITY_NORMAL : DC_CHAT_VISIBILITY_PINNED)
|
|
|
+ let pinAction = UITableViewRowAction(style: .destructive, title: String.localized(pinned ? "unpin" : "pin")) { [unowned self] _, _ in
|
|
|
+ self.viewModel.pinChatToggle(chatId: chat.id)
|
|
|
}
|
|
|
- pin.backgroundColor = UIColor.systemGreen
|
|
|
+ pinAction.backgroundColor = UIColor.systemGreen
|
|
|
|
|
|
- let delete = UITableViewRowAction(style: .normal, title: String.localized("delete")) { [unowned self] _, _ in
|
|
|
+ let deleteAction = UITableViewRowAction(style: .normal, title: String.localized("delete")) { [unowned self] _, _ in
|
|
|
self.showDeleteChatConfirmationAlert(chatId: chatId)
|
|
|
}
|
|
|
- delete.backgroundColor = UIColor.systemRed
|
|
|
+ deleteAction.backgroundColor = UIColor.systemRed
|
|
|
|
|
|
- return [archive, pin, delete]
|
|
|
+ return [archiveAction, pinAction, deleteAction]
|
|
|
}
|
|
|
|
|
|
- func getDeaddropCell(_ tableView: UITableView) -> ContactCell {
|
|
|
- let deaddropCell: ContactCell
|
|
|
- if let cell = tableView.dequeueReusableCell(withIdentifier: "DeaddropCell") as? ContactCell {
|
|
|
- deaddropCell = cell
|
|
|
+ // MARK: updates
|
|
|
+ private func updateTitle() {
|
|
|
+ if RelayHelper.sharedInstance.isForwarding() {
|
|
|
+ title = String.localized("forward_to")
|
|
|
+ if !viewModel.isArchive {
|
|
|
+ navigationItem.setLeftBarButton(cancelButton, animated: true)
|
|
|
+ }
|
|
|
} else {
|
|
|
- deaddropCell = ContactCell(style: .default, reuseIdentifier: "DeaddropCell")
|
|
|
+ title = viewModel.isArchive ? String.localized("chat_archived_chats_title") :
|
|
|
+ String.localized("pref_chats")
|
|
|
+ navigationItem.setLeftBarButton(nil, animated: true)
|
|
|
}
|
|
|
- deaddropCell.backgroundColor = DcColors.deaddropBackground
|
|
|
- deaddropCell.contentView.backgroundColor = DcColors.deaddropBackground
|
|
|
- return deaddropCell
|
|
|
}
|
|
|
|
|
|
- func getArchiveCell(_ tableView: UITableView) -> UITableViewCell {
|
|
|
+ func handleChatListUpdate() {
|
|
|
+ tableView.reloadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ func getArchiveCell(_ tableView: UITableView, title: String) -> UITableViewCell {
|
|
|
let archiveCell: UITableViewCell
|
|
|
if let cell = tableView.dequeueReusableCell(withIdentifier: "ArchiveCell") {
|
|
|
archiveCell = cell
|
|
@@ -302,14 +277,12 @@ extension ChatListController: UITableViewDataSource, UITableViewDelegate {
|
|
|
archiveCell = UITableViewCell(style: .default, reuseIdentifier: "ArchiveCell")
|
|
|
}
|
|
|
archiveCell.textLabel?.textAlignment = .center
|
|
|
- var title = String.localized("chat_archived_chats_title")
|
|
|
- let count = getNumberOfArchivedChats()
|
|
|
- title.append(" (\(count))")
|
|
|
archiveCell.textLabel?.text = title
|
|
|
archiveCell.textLabel?.textColor = .systemBlue
|
|
|
return archiveCell
|
|
|
}
|
|
|
|
|
|
+ // MARK: - alerts
|
|
|
private func showDeleteChatConfirmationAlert(chatId: Int) {
|
|
|
let alert = UIAlertController(
|
|
|
title: nil,
|
|
@@ -323,32 +296,65 @@ extension ChatListController: UITableViewDataSource, UITableViewDelegate {
|
|
|
self.present(alert, animated: true, completion: nil)
|
|
|
}
|
|
|
|
|
|
- private func deleteChat(chatId: Int, animated: Bool) {
|
|
|
+ private func showDeaddropRequestAlert(msgId: Int) {
|
|
|
+ let dcMsg = DcMsg(id: msgId)
|
|
|
+ let dcContact = DcContact(id: dcMsg.fromContactId)
|
|
|
+ let title = String.localizedStringWithFormat(String.localized("ask_start_chat_with"), dcContact.nameNAddr)
|
|
|
+ let alert = UIAlertController(title: title, message: nil, preferredStyle: .safeActionSheet)
|
|
|
+ alert.addAction(UIAlertAction(title: String.localized("start_chat"), style: .default, handler: { _ in
|
|
|
+ let chat = dcMsg.createChat()
|
|
|
+ self.coordinator?.showChat(chatId: chat.id)
|
|
|
+ }))
|
|
|
+ alert.addAction(UIAlertAction(title: String.localized("not_now"), style: .default, handler: { _ in
|
|
|
+ dcContact.marknoticed()
|
|
|
+ }))
|
|
|
+ alert.addAction(UIAlertAction(title: String.localized("menu_block_contact"), style: .destructive, handler: { _ in
|
|
|
+ dcContact.block()
|
|
|
+ }))
|
|
|
+ alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel))
|
|
|
+ present(alert, animated: true, completion: nil)
|
|
|
+ }
|
|
|
|
|
|
- if !animated {
|
|
|
- dcContext.deleteChat(chatId: chatId)
|
|
|
- self.getChatList()
|
|
|
- return
|
|
|
- }
|
|
|
+ private func askToChatWith(contactId: Int) {
|
|
|
+ let dcContact = DcContact(id: contactId)
|
|
|
+ let alert = UIAlertController(
|
|
|
+ title: String.localizedStringWithFormat(String.localized("ask_start_chat_with"), dcContact.nameNAddr),
|
|
|
+ message: nil,
|
|
|
+ preferredStyle: .safeActionSheet)
|
|
|
+ alert.addAction(UIAlertAction(
|
|
|
+ title: String.localized("start_chat"),
|
|
|
+ style: .default,
|
|
|
+ handler: { _ in
|
|
|
+ self.coordinator?.showNewChat(contactId: contactId)
|
|
|
+ }))
|
|
|
+ alert.addAction(UIAlertAction(
|
|
|
+ title: String.localized("cancel"),
|
|
|
+ style: .cancel,
|
|
|
+ handler: { _ in
|
|
|
+ }))
|
|
|
+ self.present(alert, animated: true, completion: nil)
|
|
|
+ }
|
|
|
|
|
|
- guard let chatList = chatList else {
|
|
|
+ private func deleteChat(chatId: Int, animated: Bool) {
|
|
|
+ if !animated {
|
|
|
+ _ = viewModel.deleteChat(chatId: chatId)
|
|
|
+ viewModel.refreshData()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // find index of chatId
|
|
|
- let indexToDelete = Array(0..<chatList.length).filter { chatList.getChatId(index: $0) == chatId }.first
|
|
|
-
|
|
|
- guard let row = indexToDelete else {
|
|
|
- return
|
|
|
- }
|
|
|
+ let row = viewModel.deleteChat(chatId: chatId)
|
|
|
+ tableView.deleteRows(at: [IndexPath(row: row, section: 0)], with: .fade)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- var gclFlags: Int32 = 0
|
|
|
- if showArchive {
|
|
|
- gclFlags |= DC_GCL_ARCHIVED_ONLY
|
|
|
- }
|
|
|
+// MARK: - uisearchbardelegate
|
|
|
+extension ChatListController: UISearchBarDelegate {
|
|
|
+ func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
|
|
|
+ viewModel.beginSearch()
|
|
|
+ return true
|
|
|
+ }
|
|
|
|
|
|
- dcContext.deleteChat(chatId: chatId)
|
|
|
- self.chatList = dcContext.getChatlist(flags: gclFlags, queryString: nil, queryId: 0)
|
|
|
- chatTable.deleteRows(at: [IndexPath(row: row, section: 0)], with: .fade)
|
|
|
+ func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
|
|
|
+ viewModel.endSearch()
|
|
|
}
|
|
|
}
|