talk-ios/NextcloudTalk/PollCreationViewController....

372 строки
15 KiB
Swift

//
// SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//
import UIKit
@objcMembers class PollCreationViewController: UITableViewController, UITextFieldDelegate, PollDraftsViewControllerDelegate {
enum PollCreationSection: Int {
case kPollCreationSectionQuestion = 0
case kPollCreationSectionOptions
case kPollCreationSectionSettings
case kPollCreationSectionCount
}
enum PollSetting: Int {
case kPollSettingPrivate = 0
case kPollSettingMultiple
case kPollSettingCount
}
let kQuestionTextFieldTag = 9999
var room: NCRoom
var draftsAvailable: Bool = false
var question: String = ""
var options: [String] = ["", ""]
var anonymousPollSwitch = UISwitch()
var multipleAnswersSwitch = UISwitch()
var creatingPollIndicatorView = UIActivityIndicatorView()
let footerView = PollFooterView(frame: CGRect.zero)
required init?(coder aDecoder: NSCoder) {
self.room = NCRoom()
super.init(coder: aDecoder)
self.initPollCreationView()
}
init(room: NCRoom) {
self.room = room
self.draftsAvailable = room.canModerate && NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityTalkPollsDrafts, forAccountId: room.accountId)
super.init(style: .insetGrouped)
self.initPollCreationView()
}
override func viewDidLoad() {
super.viewDidLoad()
self.creatingPollIndicatorView = UIActivityIndicatorView()
self.creatingPollIndicatorView.color = NCAppBranding.themeTextColor()
self.setMoreOptionsButton()
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: NCAppBranding.themeTextColor()]
self.navigationController?.navigationBar.tintColor = NCAppBranding.themeTextColor()
self.navigationController?.navigationBar.barTintColor = NCAppBranding.themeColor()
self.navigationController?.navigationBar.isTranslucent = false
self.navigationItem.title = NSLocalizedString("New poll", comment: "")
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [.foregroundColor: NCAppBranding.themeTextColor()]
appearance.backgroundColor = NCAppBranding.themeColor()
self.navigationItem.standardAppearance = appearance
self.navigationItem.compactAppearance = appearance
self.navigationItem.scrollEdgeAppearance = appearance
self.tableView.isEditing = true
// Set footer buttons
self.tableView.tableFooterView = pollFooterView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.cancelButtonPressed))
self.navigationItem.leftBarButtonItem?.tintColor = NCAppBranding.themeTextColor()
}
override func viewDidAppear(_ animated: Bool) {
if let questionCell = self.tableView.cellForRow(at: IndexPath(row: 0, section: PollCreationSection.kPollCreationSectionQuestion.rawValue)) as? TextFieldTableViewCell {
questionCell.textField.becomeFirstResponder()
}
}
func cancelButtonPressed() {
close()
}
func close() {
self.dismiss(animated: true, completion: nil)
}
func presentPollDraftsView() {
let pollDraftsVC = PollDraftsViewController(room: room)
pollDraftsVC.delegate = self
let navController = UINavigationController(rootViewController: pollDraftsVC)
present(navController, animated: true, completion: nil)
}
func didSelectPollDraft(question: String, options: [String], resultMode: NCPollResultMode, maxVotes: Int) {
// End editing for any textfield
self.view.endEditing(true)
// Assign poll draft values
self.question = question
self.options = options
self.anonymousPollSwitch.isOn = resultMode == .hidden
self.multipleAnswersSwitch.isOn = maxVotes == 0
self.tableView.reloadData()
self.checkIfPollIsReadyToCreate()
}
func showCreationError() {
let alert = UIAlertController(title: NSLocalizedString("Creating poll failed", comment: ""),
message: NSLocalizedString("An error occurred while creating the poll", comment: ""),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel, handler: nil))
self.present(alert, animated: true)
removePollCreationUI()
}
func showDraftCreationSuccess() {
NotificationPresenter.shared().present(text: NSLocalizedString("Poll draft has been saved", comment: ""), dismissAfterDelay: 5.0, includedStyle: .dark)
removePollCreationUI()
}
func showPollCreationUI() {
disablePollCreationButtons()
creatingPollIndicatorView.startAnimating()
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: creatingPollIndicatorView)
}
func removePollCreationUI() {
enablePollCreationButtons()
creatingPollIndicatorView.stopAnimating()
setMoreOptionsButton()
}
func setMoreOptionsButton() {
if draftsAvailable {
let menuAction = UIAction(
title: NSLocalizedString("Browse poll drafts", comment: ""),
image: UIImage(systemName: "doc")) { _ in
self.presentPollDraftsView()
}
let menu = UIMenu(children: [menuAction])
let menuButton = UIBarButtonItem(
image: UIImage(systemName: "ellipsis.circle"),
menu: menu
)
navigationItem.rightBarButtonItem = menuButton
} else {
navigationItem.rightBarButtonItem = nil
}
}
func enablePollCreationButtons() {
footerView.primaryButton.setButtonEnabled(enabled: true)
footerView.secondaryButton.setButtonEnabled(enabled: true)
}
func disablePollCreationButtons() {
footerView.primaryButton.setButtonEnabled(enabled: false)
footerView.secondaryButton.setButtonEnabled(enabled: false)
}
func pollFooterView() -> UIView {
footerView.primaryButton.setTitle(NSLocalizedString("Create poll", comment: ""), for: .normal)
footerView.primaryButton.setButtonAction(target: self, selector: #selector(createPollButtonPressed))
footerView.frame = CGRect(x: 0, y: 0, width: 0, height: PollFooterView.heightForOption)
footerView.secondaryButtonContainerView.isHidden = true
if draftsAvailable {
footerView.secondaryButton.setTitle(NSLocalizedString("Save as draft", comment: ""), for: .normal)
footerView.secondaryButton.setButtonStyle(style: .tertiary)
footerView.secondaryButton.setButtonAction(target: self, selector: #selector(createPollDraftButtonPressed))
footerView.frame.size.height += PollFooterView.heightForOption
footerView.secondaryButtonContainerView.isHidden = false
}
checkIfPollIsReadyToCreate()
return footerView
}
func createPollButtonPressed() {
createPoll(asDraft: false)
}
func createPollDraftButtonPressed() {
createPoll(asDraft: true)
}
func createPoll(asDraft: Bool) {
let resultMode: NCPollResultMode = anonymousPollSwitch.isOn ? .hidden : .public
let maxVotes: Int = multipleAnswersSwitch.isOn ? 0 : 1
showPollCreationUI()
NCAPIController.sharedInstance().createPoll(withQuestion: question, options: options, resultMode: resultMode, maxVotes: maxVotes, inRoom: room.token, asDraft: asDraft, for: room.account) { _, error, _ in
if error != nil {
self.showCreationError()
} else if asDraft {
self.showDraftCreationSuccess()
} else {
self.close()
}
}
}
func checkIfPollIsReadyToCreate() {
disablePollCreationButtons()
if !question.isEmpty && options.filter({!$0.isEmpty}).count >= 2 {
enablePollCreationButtons()
}
}
func initPollCreationView() {
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.keyboardDismissMode = UIScrollView.KeyboardDismissMode.onDrag
self.tableView.register(TextFieldTableViewCell.self, forCellReuseIdentifier: TextFieldTableViewCell.identifier)
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.section == PollCreationSection.kPollCreationSectionOptions.rawValue {
return true
}
return false
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
if indexPath.section == PollCreationSection.kPollCreationSectionOptions.rawValue {
if indexPath.row == options.count {
return .insert
}
if indexPath.row > 1 || options.count > 2 {
return .delete
}
}
return .none
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if indexPath.section == PollCreationSection.kPollCreationSectionOptions.rawValue {
if indexPath.row == options.count {
options.insert("", at: indexPath.row)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
if let optionCell = self.tableView.cellForRow(at: indexPath) as? TextFieldTableViewCell {
optionCell.textField.becomeFirstResponder()
}
} else {
options.remove(at: indexPath.row)
self.tableView.reloadSections([PollCreationSection.kPollCreationSectionOptions.rawValue], with: .automatic)
}
checkIfPollIsReadyToCreate()
}
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
override func numberOfSections(in tableView: UITableView) -> Int {
return PollCreationSection.kPollCreationSectionCount.rawValue
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == PollCreationSection.kPollCreationSectionQuestion.rawValue {
return 1
} else if section == PollCreationSection.kPollCreationSectionOptions.rawValue {
return options.count + 1
} else if section == PollCreationSection.kPollCreationSectionSettings.rawValue {
return PollSetting.kPollSettingCount.rawValue
}
return 0
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == PollCreationSection.kPollCreationSectionQuestion.rawValue {
return NSLocalizedString("Question", comment: "")
} else if section == PollCreationSection.kPollCreationSectionOptions.rawValue {
return NSLocalizedString("Answers", comment: "")
} else if section == PollCreationSection.kPollCreationSectionSettings.rawValue {
return NSLocalizedString("Settings", comment: "")
}
return nil
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == PollCreationSection.kPollCreationSectionQuestion.rawValue {
let textInputCell: TextFieldTableViewCell = tableView.dequeueOrCreateCell(withIdentifier: TextFieldTableViewCell.identifier)
textInputCell.textField.delegate = self
textInputCell.textField.placeholder = NSLocalizedString("Ask a question", comment: "")
textInputCell.textField.tag = kQuestionTextFieldTag
textInputCell.textField.text = question
return textInputCell
} else if indexPath.section == PollCreationSection.kPollCreationSectionOptions.rawValue {
if indexPath.row == options.count {
let actionCell = tableView.dequeueOrCreateCell(withIdentifier: "PollSettingCellIdentifier")
actionCell.textLabel?.text = NSLocalizedString("Add answer", comment: "")
return actionCell
} else if indexPath.row < options.count {
let textInputCell: TextFieldTableViewCell = tableView.dequeueOrCreateCell(withIdentifier: TextFieldTableViewCell.identifier)
textInputCell.textField.delegate = self
textInputCell.textField.placeholder = NSLocalizedString("Answer", comment: "") + " " + String(indexPath.row + 1)
textInputCell.textField.tag = indexPath.row
textInputCell.textField.text = options[indexPath.row]
return textInputCell
}
} else if indexPath.section == PollCreationSection.kPollCreationSectionSettings.rawValue {
if indexPath.row == PollSetting.kPollSettingPrivate.rawValue {
let actionCell = tableView.dequeueOrCreateCell(withIdentifier: "PollSettingCellIdentifier")
actionCell.textLabel?.text = NSLocalizedString("Anonymous poll", comment: "")
actionCell.accessoryView = anonymousPollSwitch
return actionCell
} else if indexPath.row == PollSetting.kPollSettingMultiple.rawValue {
let actionCell = tableView.dequeueOrCreateCell(withIdentifier: "PollSettingCellIdentifier")
actionCell.textLabel?.text = NSLocalizedString("Multiple answers", comment: "")
actionCell.accessoryView = multipleAnswersSwitch
return actionCell
}
}
return UITableViewCell()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
// MARK: - UITextField delegate
func textFieldDidEndEditing(_ textField: UITextField) {
let value = textField.text!.trimmingCharacters(in: CharacterSet.whitespaces)
textField.text = value
setValueFromTextField(textField: textField, value: value)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let value = (textField.text as NSString?)?.replacingCharacters(in: range, with: string).trimmingCharacters(in: CharacterSet.whitespaces)
setValueFromTextField(textField: textField, value: value ?? "")
return true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
setValueFromTextField(textField: textField, value: "")
return true
}
func setValueFromTextField(textField: UITextField, value: String) {
if textField.tag == kQuestionTextFieldTag {
question = value
} else if textField.tag < options.count {
options[textField.tag] = value
}
checkIfPollIsReadyToCreate()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}