Antidote/Antidote/FriendListController.swift

316 lines
11 KiB
Swift

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import UIKit
import SnapKit
protocol FriendListControllerDelegate: class {
func friendListController(_ controller: FriendListController, didSelectFriend friend: OCTFriend)
func friendListController(_ controller: FriendListController, didSelectRequest request: OCTFriendRequest)
func friendListControllerAddFriend(_ controller: FriendListController)
func friendListController(_ controller: FriendListController, showQRCodeWithText text: String)
}
class FriendListController: UIViewController {
weak var delegate: FriendListControllerDelegate?
fileprivate let theme: Theme
fileprivate var dataSource: FriendListDataSource!
fileprivate weak var submanagerObjects: OCTSubmanagerObjects!
fileprivate weak var submanagerFriends: OCTSubmanagerFriends!
fileprivate weak var submanagerChats: OCTSubmanagerChats!
fileprivate weak var submanagerUser: OCTSubmanagerUser!
fileprivate var placeholderView: UITextView!
fileprivate var tableView: UITableView!
init(theme: Theme, submanagerObjects: OCTSubmanagerObjects, submanagerFriends: OCTSubmanagerFriends, submanagerChats: OCTSubmanagerChats, submanagerUser: OCTSubmanagerUser) {
self.theme = theme
self.submanagerObjects = submanagerObjects
self.submanagerFriends = submanagerFriends
self.submanagerChats = submanagerChats
self.submanagerUser = submanagerUser
super.init(nibName: nil, bundle: nil)
addNavigationButtons()
edgesForExtendedLayout = UIRectEdge()
title = String(localized: "contacts_title")
}
required convenience init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
loadViewWithBackgroundColor(theme.colorForType(.NormalBackground))
createTableView()
createPlaceholderView()
installConstraints()
}
override func viewDidLoad() {
super.viewDidLoad()
let friends = submanagerObjects.friends()
let requests = submanagerObjects.friendRequests()
dataSource = FriendListDataSource(theme: theme, friends: friends, requests: requests)
dataSource.delegate = self
// removing separators on empty lines
tableView.tableFooterView = UIView()
updateViewsVisibility()
let message = "Antidote is Tox"
let echobotid = "76518406F6A9F2217E8DC487CC783C25CC16A15EB36FF32E335A235342C48A39218F515C39A6"
print("EchobotAdded=\(UserDefaultsManager().EchobotAdded)")
if (UserDefaultsManager().EchobotAdded == false) {
do {
//try self.submanagerFriends.sendFriendRequest(toAddress: echobotid, message: message)
UserDefaultsManager().EchobotAdded = true
}
catch let error as NSError {
return
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateViewsVisibility()
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
tableView.setEditing(editing, animated: animated)
}
}
extension FriendListController {
@objc func addFriendButtonPressed() {
delegate?.friendListControllerAddFriend(self)
}
}
extension FriendListController: FriendListDataSourceDelegate {
func friendListDataSourceBeginUpdates() {
tableView.beginUpdates()
}
func friendListDataSourceEndUpdates() {
tableView.endUpdates()
updateViewsVisibility()
}
func friendListDataSourceInsertRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.insertRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceDeleteRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.deleteRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceReloadRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.reloadRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceInsertSections(_ sections: IndexSet) {
tableView.insertSections(sections, with: .automatic)
}
func friendListDataSourceDeleteSections(_ sections: IndexSet) {
tableView.deleteSections(sections, with: .automatic)
}
func friendListDataSourceReloadSections(_ sections: IndexSet) {
tableView.reloadSections(sections, with: .automatic)
}
func friendListDataSourceReloadTable() {
tableView.reloadData()
}
}
extension FriendListController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: FriendListCell.staticReuseIdentifier) as! FriendListCell
let model = dataSource.modelAtIndexPath(indexPath)
cell.setupWithTheme(theme, model: model)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.numberOfSections()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.numberOfRowsInSection(section)
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return dataSource.sectionIndexTitles()
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return dataSource.titleForHeaderInSection(section)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let title: String
switch dataSource.objectAtIndexPath(indexPath) {
case .request:
title = String(localized:"delete_contact_request_title")
case .friend:
title = String(localized:"delete_contact_title")
}
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: String(localized: "alert_cancel"), style: .default, handler: nil))
alert.addAction(UIAlertAction(title: String(localized: "alert_delete"), style: .destructive) { [unowned self] _ -> Void in
switch self.dataSource.objectAtIndexPath(indexPath) {
case .request(let request):
self.submanagerFriends.remove(request)
case .friend(let friend):
do {
let chat = self.submanagerChats.getOrCreateChat(with: friend)
try self.submanagerFriends.remove(friend)
self.submanagerChats.removeAllMessages(in: chat, removeChat: true)
}
catch let error as NSError {
handleErrorWithType(.removeFriend, error: error)
}
}
})
present(alert, animated: true, completion: nil)
}
}
}
extension FriendListController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch dataSource.objectAtIndexPath(indexPath) {
case .request(let request):
didSelectFriendRequest(request)
case .friend(let friend):
delegate?.friendListController(self, didSelectFriend: friend)
}
}
}
extension FriendListController : UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
if textView === placeholderView {
let toxId = submanagerUser.userAddress
let alert = UIAlertController(title: String(localized: "my_tox_id"), message: toxId, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: String(localized: "copy"), style: .default) { _ -> Void in
UIPasteboard.general.string = toxId
})
alert.addAction(UIAlertAction(title: String(localized: "show_qr_code"), style: .default) { [weak self] _ -> Void in
self?.delegate?.friendListController(self!, showQRCodeWithText: toxId)
})
alert.addAction(UIAlertAction(title: String(localized: "alert_cancel"), style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
return false
}
}
private extension FriendListController {
func addNavigationButtons() {
navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(FriendListController.addFriendButtonPressed))
}
func updateViewsVisibility() {
var isEmpty = true
for section in 0..<dataSource.numberOfSections() {
if dataSource.numberOfRowsInSection(section) > 0 {
isEmpty = false
break
}
}
navigationItem.leftBarButtonItem = isEmpty ? nil : editButtonItem
placeholderView.isHidden = !isEmpty
}
func createTableView() {
tableView = UITableView()
tableView.estimatedRowHeight = 44.0
tableView.dataSource = self
tableView.delegate = self
tableView.backgroundColor = theme.colorForType(.NormalBackground)
tableView.sectionIndexColor = theme.colorForType(.LinkText)
view.addSubview(tableView)
tableView.register(FriendListCell.self, forCellReuseIdentifier: FriendListCell.staticReuseIdentifier)
}
func createPlaceholderView() {
let top = String(localized: "contact_no_contacts_add_contact")
let bottom = String(localized: "contact_no_contacts_share_tox_id")
let text = NSMutableAttributedString(string: "\(top)\(bottom)")
let linkRange = NSRange(location: top.count, length: bottom.count)
let fullRange = NSRange(location: 0, length: text.length)
text.addAttribute(NSAttributedStringKey.foregroundColor, value: theme.colorForType(.EmptyScreenPlaceholderText), range: fullRange)
text.addAttribute(NSAttributedStringKey.font, value: UIFont.antidoteFontWithSize(26.0, weight: .light), range: fullRange)
text.addAttribute(NSAttributedStringKey.link, value: "", range: linkRange)
placeholderView = UITextView()
placeholderView.delegate = self
placeholderView.attributedText = text
placeholderView.isEditable = false
placeholderView.isScrollEnabled = false
placeholderView.textAlignment = .center
placeholderView.linkTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue : theme.colorForType(.LinkText)]
view.addSubview(placeholderView)
}
func installConstraints() {
tableView.snp.makeConstraints {
$0.edges.equalTo(view)
}
placeholderView.snp.makeConstraints {
$0.center.equalTo(view)
$0.size.equalTo(placeholderView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)))
}
}
func didSelectFriendRequest(_ request: OCTFriendRequest) {
delegate?.friendListController(self, didSelectRequest: request)
}
}