зеркало из https://github.com/nextcloud/talk-ios.git
372 строки
15 KiB
Swift
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
|
|
}
|
|
}
|