|
@@ -11,26 +11,11 @@ import NCCommunication
|
|
|
import SVGKit
|
|
|
import CloudKit
|
|
|
|
|
|
-protocol NCShareDetail {
|
|
|
- var share: TableShareable! { get }
|
|
|
-}
|
|
|
-
|
|
|
-extension NCShareDetail where Self: UIViewController {
|
|
|
- func setNavigationTitle() {
|
|
|
- title = NSLocalizedString("_share_", comment: "") + " – "
|
|
|
- if share.shareType == 0 {
|
|
|
- title! += share.shareWithDisplayname.isEmpty ? share.shareWith : share.shareWithDisplayname
|
|
|
- } else {
|
|
|
- title! += share.label.isEmpty ? NSLocalizedString("_share_link_", comment: "") : share.label
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDelegate, NCShareDetail {
|
|
|
func dismissShareAdvanceView(shouldSave: Bool) {
|
|
|
defer { navigationController?.popViewController(animated: true) }
|
|
|
guard shouldSave else { return }
|
|
|
- if NCManageDatabase.shared.getTableShare(account: share.account, idShare: share.idShare) == nil {
|
|
|
+ if isNewShare {
|
|
|
networking?.createShare(option: share)
|
|
|
} else {
|
|
|
networking?.updateShare(option: share)
|
|
@@ -38,6 +23,7 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg
|
|
|
}
|
|
|
|
|
|
var share: TableShareable!
|
|
|
+ var isNewShare: Bool { NCManageDatabase.shared.getTableShare(account: share.account, idShare: share.idShare) == nil }
|
|
|
var metadata: tableMetadata!
|
|
|
var shareConfig: ShareConfig!
|
|
|
var networking: NCShareNetworking?
|
|
@@ -46,6 +32,10 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg
|
|
|
super.viewDidLoad()
|
|
|
self.shareConfig = ShareConfig(isDirectory: metadata.directory, share: share)
|
|
|
self.setNavigationTitle()
|
|
|
+ if #available(iOS 13.0, *) {
|
|
|
+ // disbale pull to dimiss
|
|
|
+ isModalInPresentation = true
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
override func viewWillLayoutSubviews() {
|
|
@@ -59,20 +49,19 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg
|
|
|
guard let footerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionFooter", owner: self, options: nil)?.first as? NCShareAdvancePermissionFooter) else { return }
|
|
|
footerView.setupUI(delegate: self)
|
|
|
|
|
|
- footerView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 100)
|
|
|
+ footerView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 120)
|
|
|
tableView.tableFooterView = footerView
|
|
|
- tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 100, right: 0)
|
|
|
+ tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 120, right: 0)
|
|
|
footerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
|
|
|
- footerView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
|
|
|
- footerView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
|
|
|
- footerView.heightAnchor.constraint(equalToConstant: 100).isActive = true
|
|
|
+ footerView.heightAnchor.constraint(equalToConstant: 120).isActive = true
|
|
|
+ footerView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor).isActive = true
|
|
|
}
|
|
|
|
|
|
func setupHeaderView() {
|
|
|
guard let headerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) else { return }
|
|
|
headerView.setupUI(with: metadata)
|
|
|
|
|
|
- headerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 200)
|
|
|
+ headerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 200)
|
|
|
tableView.tableHeaderView = headerView
|
|
|
headerView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
headerView.heightAnchor.constraint(equalToConstant: 200).isActive = true
|
|
@@ -148,291 +137,3 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-protocol ShareCellConfig {
|
|
|
- var title: String { get }
|
|
|
- func getCell(for share: TableShareable) -> UITableViewCell
|
|
|
- func didSelect(for share: TableShareable)
|
|
|
-}
|
|
|
-
|
|
|
-protocol ToggleCellConfig: ShareCellConfig {
|
|
|
- func isOn(for share: TableShareable) -> Bool
|
|
|
- func didChange(_ share: TableShareable, to newValue: Bool)
|
|
|
-}
|
|
|
-
|
|
|
-extension ToggleCellConfig {
|
|
|
- func getCell(for share: TableShareable) -> UITableViewCell {
|
|
|
- return ToggleCell(isOn: isOn(for: share))
|
|
|
- }
|
|
|
-
|
|
|
- func didSelect(for share: TableShareable) {
|
|
|
- didChange(share, to: !isOn(for: share))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-protocol Permission: ToggleCellConfig {
|
|
|
- static var forDirectory: [Self] { get }
|
|
|
- static var forFile: [Self] { get }
|
|
|
-}
|
|
|
-
|
|
|
-enum UserPermission: CaseIterable, Permission {
|
|
|
- var permissionBitFlag: Int {
|
|
|
- switch self {
|
|
|
- case .reshare: return NCGlobal.shared.permissionShareShare
|
|
|
- case .edit: return NCGlobal.shared.permissionUpdateShare
|
|
|
- case .create: return NCGlobal.shared.permissionCreateShare
|
|
|
- case .delete: return NCGlobal.shared.permissionDeleteShare
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func didChange(_ share: TableShareable, to newValue: Bool) {
|
|
|
- share.permissions ^= permissionBitFlag
|
|
|
- }
|
|
|
-
|
|
|
- func isOn(for share: TableShareable) -> Bool {
|
|
|
- return (share.permissions & permissionBitFlag) != 0
|
|
|
- }
|
|
|
-
|
|
|
- case reshare, edit, create, delete
|
|
|
- static let forDirectory: [UserPermission] = UserPermission.allCases
|
|
|
- static let forFile: [UserPermission] = [.reshare, .edit]
|
|
|
-
|
|
|
- var title: String {
|
|
|
- switch self {
|
|
|
- case .reshare: return NSLocalizedString("_share_can_reshare_", comment: "")
|
|
|
- case .edit: return NSLocalizedString("_share_can_change_", comment: "")
|
|
|
- case .create: return NSLocalizedString("_share_can_create_", comment: "")
|
|
|
- case .delete: return NSLocalizedString("_share_can_delete_", comment: "")
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-enum LinkPermission: Permission {
|
|
|
- func didChange(_ share: TableShareable, to newValue: Bool) {
|
|
|
- guard self != .allowEdit else {
|
|
|
- // file
|
|
|
- share.permissions = CCUtility.getPermissionsValue(
|
|
|
- byCanEdit: newValue,
|
|
|
- andCanCreate: newValue,
|
|
|
- andCanChange: newValue,
|
|
|
- andCanDelete: newValue,
|
|
|
- andCanShare: false,
|
|
|
- andIsFolder: false)
|
|
|
- return
|
|
|
- }
|
|
|
- // can't deselect, only change
|
|
|
- guard newValue == true else { return }
|
|
|
- switch self {
|
|
|
- case .allowEdit: return
|
|
|
- case .viewOnly:
|
|
|
- share.permissions = CCUtility.getPermissionsValue(
|
|
|
- byCanEdit: false,
|
|
|
- andCanCreate: false,
|
|
|
- andCanChange: false,
|
|
|
- andCanDelete: false,
|
|
|
- andCanShare: false,
|
|
|
- andIsFolder: true)
|
|
|
- case .uploadEdit:
|
|
|
- share.permissions = CCUtility.getPermissionsValue(
|
|
|
- byCanEdit: true,
|
|
|
- andCanCreate: true,
|
|
|
- andCanChange: true,
|
|
|
- andCanDelete: true,
|
|
|
- andCanShare: false,
|
|
|
- andIsFolder: true)
|
|
|
- case .fileDrop:
|
|
|
- share.permissions = NCGlobal.shared.permissionCreateShare
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func isOn(for share: TableShareable) -> Bool {
|
|
|
- switch self {
|
|
|
- case .allowEdit: return CCUtility.isAnyPermission(toEdit: share.permissions)
|
|
|
- case .viewOnly: return !CCUtility.isAnyPermission(toEdit: share.permissions) && share.permissions != NCGlobal.shared.permissionCreateShare
|
|
|
- case .uploadEdit: return CCUtility.isAnyPermission(toEdit: share.permissions) && share.permissions != NCGlobal.shared.permissionCreateShare
|
|
|
- case .fileDrop: return share.permissions == NCGlobal.shared.permissionCreateShare
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var title: String {
|
|
|
- switch self {
|
|
|
- case .allowEdit: return NSLocalizedString("_share_can_change_", comment: "")
|
|
|
- case .viewOnly: return NSLocalizedString("_share_read_only_", comment: "")
|
|
|
- case .uploadEdit: return NSLocalizedString("_share_allow_upload_", comment: "")
|
|
|
- case .fileDrop: return NSLocalizedString("_share_file_drop_", comment: "")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- case allowEdit, viewOnly, uploadEdit, fileDrop
|
|
|
- static let forDirectory: [LinkPermission] = [.viewOnly, .uploadEdit, .fileDrop]
|
|
|
- static let forFile: [LinkPermission] = [.allowEdit]
|
|
|
-}
|
|
|
-
|
|
|
-enum Advanced: CaseIterable, ShareCellConfig {
|
|
|
- func didSelect(for share: TableShareable) {
|
|
|
- switch self {
|
|
|
- case .hideDownload: share.hideDownload.toggle()
|
|
|
- case .expirationDate: return
|
|
|
- case .password: return
|
|
|
- case .note: return
|
|
|
- case .label: return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func getCell(for share: TableShareable) -> UITableViewCell {
|
|
|
- switch self {
|
|
|
- case .hideDownload:
|
|
|
- return ToggleCell(isOn: share.hideDownload)
|
|
|
- case .expirationDate:
|
|
|
- return DatePickerTableViewCell(share: share)
|
|
|
- case .password: return ToggleCell(isOn: !share.password.isEmpty, customIcons: ("lock", "lock.open"))
|
|
|
- case .note:
|
|
|
- let cell = UITableViewCell(style: .value1, reuseIdentifier: "shareNote")
|
|
|
- cell.detailTextLabel?.text = share.note
|
|
|
- cell.accessoryType = .disclosureIndicator
|
|
|
- return cell
|
|
|
- case .label:
|
|
|
- let cell = UITableViewCell(style: .value1, reuseIdentifier: "shareLabel")
|
|
|
- cell.detailTextLabel?.text = share.label
|
|
|
- return cell
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var title: String {
|
|
|
- switch self {
|
|
|
- case .hideDownload: return NSLocalizedString("_share_hide_download_", comment: "")
|
|
|
- case .expirationDate: return NSLocalizedString("_share_expiration_date_", comment: "")
|
|
|
- case .password: return NSLocalizedString("_share_password_protect_", comment: "")
|
|
|
- case .note: return NSLocalizedString("_share_note_recipient_", comment: "")
|
|
|
- case .label: return NSLocalizedString("_share_link_name_", comment: "")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- case label, hideDownload, expirationDate, password, note
|
|
|
- static let forLink: [Advanced] = Advanced.allCases
|
|
|
- static let forUser: [Advanced] = [.expirationDate, .note]
|
|
|
-}
|
|
|
-
|
|
|
-struct ShareConfig {
|
|
|
- let permissions: [Permission]
|
|
|
- let advanced: [Advanced]
|
|
|
- let share: TableShareable
|
|
|
-
|
|
|
- init(isDirectory: Bool, share: TableShareable) {
|
|
|
- self.share = share
|
|
|
- let type: Permission.Type = share.shareType == 3 ? LinkPermission.self : UserPermission.self
|
|
|
- self.permissions = isDirectory ? type.forDirectory : type.forFile
|
|
|
- self.advanced = share.shareType == 3 ? Advanced.forLink : Advanced.forUser
|
|
|
- }
|
|
|
-
|
|
|
- func cellFor(indexPath: IndexPath) -> UITableViewCell? {
|
|
|
- let cellConfig = config(for: indexPath)
|
|
|
- let cell = cellConfig?.getCell(for: share)
|
|
|
- cell?.textLabel?.text = cellConfig?.title
|
|
|
- return cell
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectRow(at indexPath: IndexPath) {
|
|
|
- let cellConfig = config(for: indexPath)
|
|
|
- cellConfig?.didSelect(for: share)
|
|
|
- }
|
|
|
-
|
|
|
- func config(for indexPath: IndexPath) -> ShareCellConfig? {
|
|
|
- if indexPath.section == 0, indexPath.row < permissions.count {
|
|
|
- return permissions[indexPath.row]
|
|
|
- } else if indexPath.section == 1, indexPath.row < advanced.count {
|
|
|
- return advanced[indexPath.row]
|
|
|
- } else { return nil }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class ToggleCell: UITableViewCell {
|
|
|
- typealias CustomToggleIcon = (onIconName: String?, offIconName: String?)
|
|
|
- init(isOn: Bool, customIcons: CustomToggleIcon? = nil) {
|
|
|
- super.init(style: .default, reuseIdentifier: "toggleCell")
|
|
|
- guard let customIcons = customIcons,
|
|
|
- let iconName = isOn ? customIcons.onIconName : customIcons.offIconName else {
|
|
|
- self.accessoryType = isOn ? .checkmark : .none
|
|
|
- return
|
|
|
- }
|
|
|
- let image = NCUtility.shared.loadImage(named: iconName, color: NCBrandColor.shared.brandElement)
|
|
|
- self.accessoryView = UIImageView(image: image)
|
|
|
- }
|
|
|
-
|
|
|
- required init?(coder: NSCoder) {
|
|
|
- fatalError("init(coder:) has not been implemented")
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension DateFormatter {
|
|
|
- static let shareExpDate: DateFormatter = {
|
|
|
- let dateFormatter = DateFormatter()
|
|
|
- dateFormatter.formatterBehavior = .behavior10_4
|
|
|
- dateFormatter.dateStyle = .medium
|
|
|
- return dateFormatter
|
|
|
- }()
|
|
|
-}
|
|
|
-
|
|
|
-open class DatePickerTableViewCell: UITableViewCell {
|
|
|
- let picker = UIDatePicker()
|
|
|
- let textField = UITextField()
|
|
|
-
|
|
|
- var onReload: (() -> Void)?
|
|
|
-
|
|
|
- init(share: TableShareable) {
|
|
|
- super.init(style: .value1, reuseIdentifier: "shareExpDate")
|
|
|
- picker.datePickerMode = .date
|
|
|
- picker.minimumDate = Date()
|
|
|
- if #available(iOS 13.4, *) {
|
|
|
- picker.preferredDatePickerStyle = .wheels
|
|
|
- }
|
|
|
- picker.action(for: .valueChanged) { datePicker in
|
|
|
- guard let datePicker = datePicker as? UIDatePicker else { return }
|
|
|
- self.detailTextLabel?.text = DateFormatter.shareExpDate.string(from: datePicker.date)
|
|
|
- }
|
|
|
- accessoryView = textField
|
|
|
-
|
|
|
- let toolbar = UIToolbar.toolbar {
|
|
|
- self.resignFirstResponder()
|
|
|
- share.expirationDate = nil
|
|
|
- self.onReload?()
|
|
|
- } completion: {
|
|
|
- self.resignFirstResponder()
|
|
|
- share.expirationDate = self.picker.date as NSDate
|
|
|
- self.onReload?()
|
|
|
- }
|
|
|
-
|
|
|
- textField.inputAccessoryView = toolbar
|
|
|
- textField.inputView = picker
|
|
|
-
|
|
|
- if let expDate = share.expirationDate {
|
|
|
- detailTextLabel?.text = DateFormatter.shareExpDate.string(from: expDate as Date)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- required public init?(coder: NSCoder) {
|
|
|
- fatalError("init(coder:) has not been implemented")
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension UIToolbar {
|
|
|
- static func toolbar(onClear: (() -> Void)?, completion: @escaping () -> Void) -> UIToolbar {
|
|
|
- let toolbar = UIToolbar()
|
|
|
- toolbar.sizeToFit()
|
|
|
- var buttons: [UIBarButtonItem] = []
|
|
|
- let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .done) {
|
|
|
- completion()
|
|
|
- }
|
|
|
- buttons.append(doneButton)
|
|
|
-
|
|
|
- if let onClear = onClear {
|
|
|
- let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
|
|
|
- let clearButton = UIBarButtonItem(title: NSLocalizedString("_clear_", comment: ""), style: .plain) {
|
|
|
- onClear()
|
|
|
- }
|
|
|
- buttons.append(contentsOf: [spaceButton, clearButton])
|
|
|
- }
|
|
|
- toolbar.setItems(buttons, animated: false)
|
|
|
- return toolbar
|
|
|
- }
|
|
|
-}
|