session-ios/SessionShareExtension/ThreadPickerVC.swift

209 lines
7.5 KiB
Swift
Raw Normal View History

import UIKit
import SignalUtilitiesKit
2021-05-06 02:36:58 +02:00
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
2021-05-06 02:36:58 +02:00
final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableViewDelegate, AttachmentApprovalViewControllerDelegate {
2021-05-06 02:36:58 +02:00
private var threads: YapDatabaseViewMappings!
private var threadViewModelCache: [String: ThreadViewModel] = [:] // Thread ID to ThreadViewModel
2021-05-06 03:09:54 +02:00
private var selectedThread: TSThread?
2021-05-06 04:48:49 +02:00
var shareVC: ShareVC?
2021-05-06 02:36:58 +02:00
private var threadCount: UInt {
threads.numberOfItems(inGroup: TSInboxGroup)
}
private lazy var dbConnection: YapDatabaseConnection = {
let result = OWSPrimaryStorage.shared().newDatabaseConnection()
result.objectCacheLimit = 500
return result
}()
// MARK: - UI
private lazy var titleLabel: UILabel = {
let titleLabel: UILabel = UILabel()
titleLabel.text = "vc_share_title".localized()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
return titleLabel
}()
2021-05-06 02:36:58 +02:00
private lazy var tableView: UITableView = {
let tableView: UITableView = UITableView()
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.register(view: SimplifiedConversationCell.self)
tableView.showsVerticalScrollIndicator = false
tableView.dataSource = self
tableView.delegate = self
return tableView
2021-05-06 02:36:58 +02:00
}()
2021-05-06 02:49:32 +02:00
private lazy var fadeView: UIView = {
let view = UIView()
2021-05-06 02:49:32 +02:00
let gradient = Gradients.homeVCFade
view.setGradient(gradient)
view.isUserInteractionEnabled = false
return view
2021-05-06 02:49:32 +02:00
}()
// MARK: - Lifecycle
2021-05-06 02:36:58 +02:00
override func viewDidLoad() {
super.viewDidLoad()
2021-10-01 01:30:45 +02:00
setupNavBar()
2021-05-06 02:36:58 +02:00
// Gradient
view.backgroundColor = .clear
view.setGradient(Gradients.defaultBackground)
2021-05-06 02:36:58 +02:00
// Threads
dbConnection.beginLongLivedReadTransaction() // Freeze the connection for use on the main thread (this gives us a stable data source that doesn't change until we tell it to)
threads = YapDatabaseViewMappings(groups: [ TSInboxGroup ], view: TSThreadDatabaseViewExtensionName) // The extension should be registered at this point
threads.setIsReversed(true, forGroup: TSInboxGroup)
dbConnection.read { transaction in
self.threads.update(with: transaction) // Perform the initial update
}
2021-05-06 02:36:58 +02:00
// Title
navigationItem.titleView = titleLabel
2021-05-06 02:36:58 +02:00
// Table view
2021-05-06 02:36:58 +02:00
view.addSubview(tableView)
2021-05-06 02:49:32 +02:00
view.addSubview(fadeView)
setupLayout()
2021-05-06 02:36:58 +02:00
// Reload
reload()
}
2021-10-01 01:30:45 +02:00
private func setupNavBar() {
guard let navigationBar = navigationController?.navigationBar else { return }
if #available(iOS 15.0, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = Colors.navigationBarBackground
navigationBar.standardAppearance = appearance;
navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance
}
}
// MARK: Layout
private func setupLayout() {
let topInset = 0.15 * view.height()
tableView.pin(to: view)
fadeView.pin(.leading, to: .leading, of: view)
fadeView.pin(.top, to: .top, of: view, withInset: topInset)
fadeView.pin(.trailing, to: .trailing, of: view)
fadeView.pin(.bottom, to: .bottom, of: view)
}
2021-05-06 02:36:58 +02:00
// MARK: Table View Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Int(threadCount)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: SimplifiedConversationCell = tableView.dequeue(type: SimplifiedConversationCell.self, for: indexPath)
2021-05-06 02:36:58 +02:00
cell.threadViewModel = threadViewModel(at: indexPath.row)
2021-05-06 02:36:58 +02:00
return cell
}
// MARK: - Updating
2021-05-06 02:36:58 +02:00
private func reload() {
AssertIsOnMainThread()
dbConnection.beginLongLivedReadTransaction() // Jump to the latest commit
dbConnection.read { transaction in
self.threads.update(with: transaction)
}
threadViewModelCache.removeAll()
tableView.reloadData()
}
// MARK: - Interaction
2021-05-06 02:45:30 +02:00
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
guard let thread = self.thread(at: indexPath.row), let attachments = ShareVC.attachmentPrepPromise?.value else {
return
}
self.selectedThread = thread
2021-05-06 03:09:54 +02:00
let approvalVC = AttachmentApprovalViewController.wrappedInNavController(attachments: attachments, approvalDelegate: self)
navigationController!.present(approvalVC, animated: true, completion: nil)
}
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didApproveAttachments attachments: [SignalAttachment], messageText: String?) {
let message = VisibleMessage()
message.sentTimestamp = NSDate.millisecondTimestamp()
message.text = messageText
2021-05-06 03:09:54 +02:00
let tsMessage = TSOutgoingMessage.from(message, associatedWith: selectedThread!)
Storage.write { transaction in
tsMessage.save(with: transaction)
}
2021-05-06 04:48:49 +02:00
shareVC!.dismiss(animated: true, completion: nil)
ModalActivityIndicatorViewController.present(fromViewController: shareVC!, canCancel: false, message: "vc_share_sending_message".localized()) { activityIndicator in
MessageSender.sendNonDurably(message, with: attachments, in: self.selectedThread!)
.done { [weak self] _ in
activityIndicator.dismiss { }
self?.shareVC?.shareViewWasCompleted()
}
.catch { [weak self] error in
activityIndicator.dismiss { }
self?.shareVC?.shareViewFailed(error: error)
}
2021-05-06 04:48:49 +02:00
}
2021-05-06 03:09:54 +02:00
}
func attachmentApprovalDidCancel(_ attachmentApproval: AttachmentApprovalViewController) {
2021-05-06 03:22:33 +02:00
// Do nothing
2021-05-06 03:09:54 +02:00
}
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didChangeMessageText newMessageText: String?) {
2021-05-06 03:22:33 +02:00
// Do nothing
2021-05-06 02:45:30 +02:00
}
// MARK: - Convenience
2021-05-06 02:36:58 +02:00
private func thread(at index: Int) -> TSThread? {
var thread: TSThread? = nil
dbConnection.read { transaction in
let ext = transaction.ext(TSThreadDatabaseViewExtensionName) as! YapDatabaseViewTransaction
thread = ext.object(atRow: UInt(index), inSection: 0, with: self.threads) as! TSThread?
}
return thread
}
private func threadViewModel(at index: Int) -> ThreadViewModel? {
guard let thread = thread(at: index) else { return nil }
2021-05-06 02:36:58 +02:00
if let cachedThreadViewModel = threadViewModelCache[thread.uniqueId!] {
return cachedThreadViewModel
}
else {
2021-05-06 02:36:58 +02:00
var threadViewModel: ThreadViewModel? = nil
dbConnection.read { transaction in
threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
}
threadViewModelCache[thread.uniqueId!] = threadViewModel
return threadViewModel
}
}
}