From 708467d9e9a55b432cbbf6201ddbf251d1f8aa46 Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:49:46 +0530 Subject: [PATCH 1/2] NMC 2261 - Audio record and upload customisation --- .../NextcloudUnitTests/AudioUploadTests.swift | 52 +++ .../NCAudioRecorderViewController.swift | 4 +- .../Create cloud/FolderPathCustomCell.swift | 33 ++ .../Create cloud/FolderPathCustomCell.xib | 74 ++++ .../NCCreateFormUploadVoiceNote.storyboard | 112 ++++++ .../NCCreateFormUploadVoiceNote.swift | 359 ++++++++++++++++++ .../Main/Create cloud/TextTableViewCell.swift | 94 +++++ .../Main/Create cloud/TextTableViewCell.xib | 82 ++++ 8 files changed, 808 insertions(+), 2 deletions(-) create mode 100644 Tests/NextcloudUnitTests/AudioUploadTests.swift create mode 100644 iOSClient/Main/Create cloud/FolderPathCustomCell.swift create mode 100644 iOSClient/Main/Create cloud/FolderPathCustomCell.xib create mode 100644 iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard create mode 100644 iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift create mode 100644 iOSClient/Main/Create cloud/TextTableViewCell.swift create mode 100644 iOSClient/Main/Create cloud/TextTableViewCell.xib diff --git a/Tests/NextcloudUnitTests/AudioUploadTests.swift b/Tests/NextcloudUnitTests/AudioUploadTests.swift new file mode 100644 index 0000000000..2ea01a8085 --- /dev/null +++ b/Tests/NextcloudUnitTests/AudioUploadTests.swift @@ -0,0 +1,52 @@ +// +// AudioUploadTests.swift +// NextcloudTests +// +// Created by A200020526 on 13/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import XCTest +@testable import Nextcloud + +final class AudioUploadTests: XCTestCase { + var viewController:NCAudioRecorderViewController? + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + // Step 1. Create an instance of UIStoryboard + let viewController = UIStoryboard(name: "NCAudioRecorderViewController", bundle: nil).instantiateInitialViewController() as? NCAudioRecorderViewController + // Step 3. Make the viewDidLoad() execute. + viewController?.loadViewIfNeeded() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + viewController = nil + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + + func testAudioMeterUpdateAfterDb(){ + viewController?.audioMeterDidUpdate(0.5) + XCTAssertNotNil(!(viewController?.durationLabel.text?.isEmpty ?? false)) + } + + func testStartRecorder(){ + viewController?.startStop() + XCTAssertEqual(viewController?.recording.state, nil, "Test start audio recorder") + } +} diff --git a/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift index 90b733388e..a3e0ae1a6e 100644 --- a/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift +++ b/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift @@ -51,7 +51,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { view.backgroundColor = .clear contentContainerView.backgroundColor = UIColor.lightGray - voiceRecordHUD.fillColor = UIColor.green + voiceRecordHUD.fillColor = NCBrandColor.shared.progressColorGreen60 Task { self.fileName = await NCNetworking.shared.createFileName(fileNameBase: NSLocalizedString("_untitled_", comment: "") + ".m4a", account: self.appDelegate.account, serverUrl: self.appDelegate.activeServerUrl) @@ -135,7 +135,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { } voiceRecordHUD.update(CGFloat(rate)) - voiceRecordHUD.fillColor = UIColor.green + voiceRecordHUD.fillColor = NCBrandColor.shared.progressColorGreen60 let formatter = DateComponentsFormatter() formatter.allowedUnits = [.second] diff --git a/iOSClient/Main/Create cloud/FolderPathCustomCell.swift b/iOSClient/Main/Create cloud/FolderPathCustomCell.swift new file mode 100644 index 0000000000..b7ba63f9ef --- /dev/null +++ b/iOSClient/Main/Create cloud/FolderPathCustomCell.swift @@ -0,0 +1,33 @@ +// +// FolderPathCustomCell.swift +// Nextcloud +// +// Created by Sumit on 28/04/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import Foundation + +class FolderPathCustomCell: XLFormButtonCell{ + + @IBOutlet weak var photoLabel: UILabel! + @IBOutlet weak var folderImage: UIImageView! + @IBOutlet weak var bottomLineView: UIView! + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func configure() { + super.configure() + } + + override func update() { + super.update() + if (rowDescriptor.tag == "PhotoButtonDestinationFolder"){ + bottomLineView.isHidden = true + }else{ + bottomLineView.isHidden = false + } + } +} diff --git a/iOSClient/Main/Create cloud/FolderPathCustomCell.xib b/iOSClient/Main/Create cloud/FolderPathCustomCell.xib new file mode 100644 index 0000000000..a231ae7c72 --- /dev/null +++ b/iOSClient/Main/Create cloud/FolderPathCustomCell.xib @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard new file mode 100644 index 0000000000..1b5344ccee --- /dev/null +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift new file mode 100644 index 0000000000..22354160c0 --- /dev/null +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift @@ -0,0 +1,359 @@ +// +// NCCreateFormUploadVoiceNote.swift +// Nextcloud +// +// Created by Marino Faggiana on 9/03/2019. +// Copyright © 2019 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +import UIKit +import NextcloudKit + +class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAudioPlayerDelegate, NCCreateFormUploadConflictDelegate { + + @IBOutlet weak var buttonPlayStop: UIButton! + @IBOutlet weak var labelTimer: UILabel! + @IBOutlet weak var labelDuration: UILabel! + @IBOutlet weak var progressView: UIProgressView! + + private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! + let utilityFileSystem = NCUtilityFileSystem() + let utility = NCUtility() + private var serverUrl = "" + private var titleServerUrl = "" + private var fileName = "" + private var fileNamePath = "" + private var durationPlayer: TimeInterval = 0 + private var counterSecondPlayer: TimeInterval = 0 + + private var audioPlayer: AVAudioPlayer! + private var timer = Timer() + + var cellBackgoundColor = UIColor.secondarySystemGroupedBackground + + // MARK: - View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancel)) + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save)) + self.navigationItem.leftBarButtonItem?.tintColor = NCBrandColor.shared.brand + self.navigationItem.rightBarButtonItem?.tintColor = NCBrandColor.shared.brand + + self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none + + view.backgroundColor = .systemGroupedBackground + tableView.backgroundColor = .systemGroupedBackground + cellBackgoundColor = .secondarySystemGroupedBackground + + self.title = NSLocalizedString("_voice_memo_title_", comment: "") + + // Button Play Stop + buttonPlayStop.setImage(UIImage(named: "audioPlay")!.image(color: NCBrandColor.shared.iconColor, size: 100), for: .normal) + + // Progress view + progressView.progress = 0 + progressView.progressTintColor = NCBrandColor.shared.customer + progressView.trackTintColor = .white + progressView.layer.borderWidth = 1 + progressView.layer.cornerRadius = 5.0 + progressView.layer.borderColor = NCBrandColor.shared.customer.cgColor + + labelTimer.textColor = .label + labelDuration.textColor = .label + + initializeForm() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + updateTimerUI() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + if audioPlayer.isPlaying { + stop() + } + } + + public func setup(serverUrl: String, fileNamePath: String, fileName: String) { + + if serverUrl == utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) { + titleServerUrl = "/" + } else { + titleServerUrl = (serverUrl as NSString).lastPathComponent + } + + self.fileName = fileName + self.serverUrl = serverUrl + self.fileNamePath = fileNamePath + + // player + do { + try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileNamePath)) + audioPlayer.prepareToPlay() + audioPlayer.delegate = self + durationPlayer = TimeInterval(audioPlayer.duration) + } catch { + buttonPlayStop.isEnabled = false + } + } + + // MARK: XLForm + + func initializeForm() { + + let form: XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section: XLFormSectionDescriptor + var row: XLFormRowDescriptor + + // Section: Destination Folder + + section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_save_path_", comment: "").uppercased()) + section.footerTitle = "" + form.addFormSection(section) + + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFolderCustomCellType"] = FolderPathCustomCell.self + + row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: "kNMCFolderCustomCellType", title: self.titleServerUrl) + row.cellConfig["backgroundColor"] = UIColor.secondarySystemGroupedBackground + row.action.formSelector = #selector(changeDestinationFolder(_:)) + row.cellConfig["folderImage.image"] = UIImage(named: "folder_nmcloud")?.image(color: NCBrandColor.shared.brandElement, size: 25) + row.cellConfig["photoLabel.textAlignment"] = NSTextAlignment.right.rawValue + row.cellConfig["photoLabel.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["photoLabel.textColor"] = UIColor.label //photos + if(self.titleServerUrl == "/"){ + row.cellConfig["photoLabel.text"] = NSLocalizedString("_prefix_upload_path_", comment: "") + }else{ + row.cellConfig["photoLabel.text"] = self.titleServerUrl + } + row.cellConfig["textLabel.text"] = "" + section.addFormRow(row) + + // Section: File Name + + XLFormViewController.cellClassesForRowDescriptorTypes()["kMyAppCustomCellType"] = TextTableViewCell.self + + section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_filename_", comment: "").uppercased()) + form.addFormSection(section) + + row = XLFormRowDescriptor(tag: "fileName", rowType: "kMyAppCustomCellType", title: NSLocalizedString("_filename_", comment: "")) + row.cellClass = TextTableViewCell.self + row.cellConfigAtConfigure["backgroundColor"] = UIColor.secondarySystemGroupedBackground; + row.cellConfig["fileNameTextField.textAlignment"] = NSTextAlignment.left.rawValue + row.cellConfig["fileNameTextField.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["fileNameTextField.textColor"] = UIColor.label + row.cellConfig["fileNameTextField.text"] = self.fileName + section.addFormRow(row) + + self.form = form + } + + override func formRowDescriptorValueHasChanged(_ formRow: XLFormRowDescriptor!, oldValue: Any!, newValue: Any!) { + + super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue) + + if formRow.tag == "fileName" { + + self.form.delegate = nil + + if let fileNameNew = formRow.value as? String { + self.fileName = utility.removeForbiddenCharacters(fileNameNew) + } + + + self.form.delegate = self + } + } + + // MARK: TableViewDelegate + + override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { + let header = view as? UITableViewHeaderFooterView + header?.textLabel?.font = UIFont.systemFont(ofSize: 13.0) + header?.textLabel?.textColor = .gray + header?.tintColor = cellBackgoundColor + } + + // MARK: - Action + + func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], indexPath: [IndexPath], overwrite: Bool, copy: Bool, move: Bool) { + + if serverUrl != nil { + + self.serverUrl = serverUrl! + + if serverUrl == utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) { + self.titleServerUrl = "/" + } else { + self.titleServerUrl = (serverUrl! as NSString).lastPathComponent + } + + // Update + let row: XLFormRowDescriptor = self.form.formRow(withTag: "ButtonDestinationFolder")! + row.cellConfig["photoLabel.text"] = self.titleServerUrl + self.updateFormRow(row) + } + } + + @objc func save() { + + let rowFileName: XLFormRowDescriptor = self.form.formRow(withTag: "fileName")! + guard let name = (rowFileName.value as? String)?.trimmingCharacters(in: .whitespaces) else { + let alert = UIAlertController(title: "", message: NSLocalizedString("_prompt_insert_file_name", comment: ""), preferredStyle: .alert) + alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .cancel, handler: nil)) + self.present(alert, animated: true) + return + } + let ext = (name as NSString).pathExtension.uppercased() + var fileNameSave = "" + + if ext.isEmpty { + fileNameSave = name + ".m4a" + } else { + fileNameSave = (name as NSString).deletingPathExtension + ".m4a" + } + + let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "") + + metadataForUpload.session = NCNetworking.shared.sessionUploadBackground + metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile + metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload + metadataForUpload.size = utilityFileSystem.getFileSize(filePath: fileNamePath) + + if NCManageDatabase.shared.getMetadataConflict(account: appDelegate.account, serverUrl: serverUrl, fileNameView: fileNameSave) != nil { + + guard let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict else { return } + + conflict.textLabelDetailNewFile = NSLocalizedString("_now_", comment: "") + conflict.serverUrl = serverUrl + conflict.metadatasUploadInConflict = [metadataForUpload] + conflict.delegate = self + + self.present(conflict, animated: true, completion: nil) + + } else { + + dismissAndUpload(metadataForUpload) + } + } + + func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) { + + if let metadatas, metadatas.count > 0 { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.dismissAndUpload(metadatas[0]) + } + } + } + + func dismissAndUpload(_ metadata: tableMetadata) { + + utilityFileSystem.copyFile(atPath: self.fileNamePath, toPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)) + + NCNetworkingProcessUpload.shared.createProcessUploads(metadatas: [metadata], completion: { _ in }) + + self.dismiss(animated: true, completion: nil) + } + + @objc func cancel() { + + try? FileManager.default.removeItem(atPath: fileNamePath) + self.dismiss(animated: true, completion: nil) + } + + @objc func changeDestinationFolder(_ sender: XLFormRowDescriptor) { + + self.deselectFormRow(sender) + + let storyboard = UIStoryboard(name: "NCSelect", bundle: nil) + if let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController, + let viewController = navigationController.topViewController as? NCSelect { + + viewController.delegate = self + viewController.typeOfCommandView = .selectCreateFolder + viewController.includeDirectoryE2EEncryption = true + + self.present(navigationController, animated: true, completion: nil) + } + } + + // MARK: Player - Timer + + func updateTimerUI() { + labelTimer.text = String().formatSecondsToString(counterSecondPlayer) + labelDuration.text = String().formatSecondsToString(durationPlayer) + progressView.progress = Float(counterSecondPlayer / durationPlayer) + } + + @objc func updateTimer() { + counterSecondPlayer += 1 + updateTimerUI() + } + + @IBAction func playStop(_ sender: Any) { + + if audioPlayer.isPlaying { + + stop() + + } else { + + start() + } + } + + func start() { + + audioPlayer.prepareToPlay() + audioPlayer.play() + + timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true) + + buttonPlayStop.setImage(UIImage(named: "stop")!.image(color: UIColor.systemGray, size: 100), for: .normal) + } + + func stop() { + + audioPlayer.currentTime = 0.0 + audioPlayer.stop() + + timer.invalidate() + counterSecondPlayer = 0 + progressView.progress = 0 + updateTimerUI() + + buttonPlayStop.setImage(UIImage(named: "audioPlay")!.image(color: UIColor.systemGray, size: 100), for: .normal) + } + + func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + + timer.invalidate() + counterSecondPlayer = 0 + progressView.progress = 0 + updateTimerUI() + + buttonPlayStop.setImage(UIImage(named: "audioPlay")!.image(color: UIColor.systemGray, size: 100), for: .normal) + } +} diff --git a/iOSClient/Main/Create cloud/TextTableViewCell.swift b/iOSClient/Main/Create cloud/TextTableViewCell.swift new file mode 100644 index 0000000000..11116a2ff5 --- /dev/null +++ b/iOSClient/Main/Create cloud/TextTableViewCell.swift @@ -0,0 +1,94 @@ +// +// TextTableViewCell.swift +// Nextcloud +// +// Created by Ashu on 23/04/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import UIKit + +class TextTableViewCell: XLFormBaseCell, UITextFieldDelegate { + + @IBOutlet weak var fileNameTextField: UITextField! + @IBOutlet weak var topLineView: UIView! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + + fileNameTextField.delegate = self + topLineView.backgroundColor = UIColor.secondarySystemBackground + + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override func configure() { + super.configure() + } + + override func update() { + super.update() + if (rowDescriptor.tag == "maskFileName"){ + topLineView.isHidden = true + }else{ + topLineView.isHidden = false + } + + fileNameTextField.tintColor = UIColor.systemGray + fileNameTextField.selectedTextRange = fileNameTextField.textRange(from: fileNameTextField.beginningOfDocument, to: fileNameTextField.endOfDocument) + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + + if fileNameTextField == textField { + if let rowDescriptor = rowDescriptor, let text = self.fileNameTextField.text { + + if (text + " ").isEmpty == false { + rowDescriptor.value = self.fileNameTextField.text! + string + } else { + rowDescriptor.value = nil + } + } + } + + self.formViewController().textField(textField, shouldChangeCharactersIn: range, replacementString: string) + + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldReturn(fileNameTextField) + return true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldClear(fileNameTextField) + rowDescriptor.value = nil + + self.formViewController().textField(textField, shouldChangeCharactersIn: NSRange.init().self, replacementString: "") + return true + } + + override class func formDescriptorCellHeight(for rowDescriptor: XLFormRowDescriptor!) -> CGFloat { + return 45 + } +} + +extension UITextField { + @IBInspectable var placeholderColor: UIColor { + get { + return attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .clear + } + set { + guard let attributedPlaceholder = attributedPlaceholder else { return } + let attributes: [NSAttributedString.Key: UIColor] = [.foregroundColor: newValue] + self.attributedPlaceholder = NSAttributedString(string: attributedPlaceholder.string, attributes: attributes) + } + } +} diff --git a/iOSClient/Main/Create cloud/TextTableViewCell.xib b/iOSClient/Main/Create cloud/TextTableViewCell.xib new file mode 100644 index 0000000000..e4be37d230 --- /dev/null +++ b/iOSClient/Main/Create cloud/TextTableViewCell.xib @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From cfc4c428b0ef72f718e328f0112069722980d7bb Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:06:22 +0530 Subject: [PATCH 2/2] NMC 2261 - Empty filename alert issue --- .../Main/Create cloud/NCCreateFormUploadVoiceNote.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift index 22354160c0..f833e106dc 100644 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift @@ -180,6 +180,8 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud if let fileNameNew = formRow.value as? String { self.fileName = utility.removeForbiddenCharacters(fileNameNew) + } else { + self.fileName = "" } @@ -218,9 +220,8 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud } @objc func save() { - - let rowFileName: XLFormRowDescriptor = self.form.formRow(withTag: "fileName")! - guard let name = (rowFileName.value as? String)?.trimmingCharacters(in: .whitespaces) else { + let name = self.fileName + guard name.trimmingCharacters(in: .whitespaces) != "" else { let alert = UIAlertController(title: "", message: NSLocalizedString("_prompt_insert_file_name", comment: ""), preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .cancel, handler: nil)) self.present(alert, animated: true)