From 1761a33b7403e108e2a456741516be172c7b755b Mon Sep 17 00:00:00 2001 From: Mike Schreiber Date: Fri, 30 Aug 2024 13:31:40 -0700 Subject: [PATCH 1/2] Properly deprecate `UITextItemInteraction` --- ...leViewHeaderFooterViewDemoController.swift | 15 +++---- .../TableViewHeaderFooterView.swift | 39 +++++++++++++++---- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift b/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift index 049294dfd..31d500fd0 100644 --- a/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift +++ b/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift @@ -133,11 +133,9 @@ extension TableViewHeaderFooterViewDemoController { } footer?.setup(style: .footer, attributedTitle: title) -#if os(iOS) if section.hasCustomLinkHandler { footer?.delegate = self } -#endif } footer?.titleNumberOfLines = section.numberOfLines footer?.tokenSet.replaceAllOverrides(with: overrideTokens) @@ -165,16 +163,15 @@ extension TableViewHeaderFooterViewDemoController { // MARK: - TableViewHeaderFooterViewDemoController: TableViewHeaderFooterViewDelegate -#if os(iOS) extension TableViewHeaderFooterViewDemoController: TableViewHeaderFooterViewDelegate { - func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { - let alertController = UIAlertController(title: "Link tapped", message: nil, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) - present(alertController, animated: true, completion: nil) - return false + func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? { + return UIAction { [weak self] _ in + let alertController = UIAlertController(title: "Link tapped", message: nil, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self?.present(alertController, animated: true, completion: nil) + } } } -#endif extension TableViewHeaderFooterViewDemoController: DemoAppearanceDelegate { func themeWideOverrideDidChange(isOverrideEnabled: Bool) { diff --git a/ios/FluentUI/Table View/TableViewHeaderFooterView.swift b/ios/FluentUI/Table View/TableViewHeaderFooterView.swift index 6ccae6b21..8e76bcdc6 100644 --- a/ios/FluentUI/Table View/TableViewHeaderFooterView.swift +++ b/ios/FluentUI/Table View/TableViewHeaderFooterView.swift @@ -7,13 +7,32 @@ import UIKit // MARK: TableViewHeaderFooterViewDelegate -#if os(iOS) @objc(MSFTableViewHeaderFooterViewDelegate) public protocol TableViewHeaderFooterViewDelegate: AnyObject { /// Returns: true if the interaction with the header view should be allowed; false if the interaction should not be allowed. + @available(iOS, deprecated: 17, message: "Replaced by primaryActionForTextItem: and menuConfigurationForTextItem: for additional customization options.") + @available(visionOS, deprecated: 1, message: "Replaced by primaryActionForTextItem: and menuConfigurationForTextItem: for additional customization options.") @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool + + /// Asks the delegate for the action to be performed when interacting with a text item. If a nil action is provided, the text view + /// will request a menu to be presented on primary action if possible. + /// + /// @param headerFooterView The `TableViewHeaderFooterView` requesting the primary action. + /// @param textItem The text item for performing said action. + /// @param defaultAction The default action for the text item. Return this to perform the default action. + /// + /// @return Return a UIAction to be performed when the text item is interacted with. Return @c nil to prevent the action from being performed. + @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? + + /// Asks the delegate for the menu configuration to be performed when interacting with a text item. + /// + /// @param headerFooterView The `TableViewHeaderFooterView` requesting the menu. + /// @param textItem The text item for performing said action. + /// @param defaultMenu The default menu for the specified text item. + /// + /// @return Return a menu configuration to be presented when the text item is interacted with. Return @c nil to prevent the menu from being presented. + @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? } -#endif // os(iOS) // MARK: - TableViewHeaderFooterView @@ -125,9 +144,7 @@ open class TableViewHeaderFooterView: UITableViewHeaderFooterView, TokenizedCont } } -#if os(iOS) @objc public weak var delegate: TableViewHeaderFooterViewDelegate? -#endif // os(iOS) open override var intrinsicContentSize: CGSize { return CGSize( @@ -407,9 +424,7 @@ open class TableViewHeaderFooterView: UITableViewHeaderFooterView, TokenizedCont open override func prepareForReuse() { super.prepareForReuse() -#if os(iOS) delegate = nil -#endif // os(iOS) accessoryButtonStyle = .regular titleNumberOfLines = 1 @@ -553,12 +568,20 @@ open class TableViewHeaderFooterView: UITableViewHeaderFooterView, TokenizedCont // MARK: - TableViewHeaderFooterView: UITextViewDelegate extension TableViewHeaderFooterView: UITextViewDelegate { -#if os(iOS) + @available(iOS, deprecated: 17, message: "Replaced by primaryActionForTextItem: and menuConfigurationForTextItem: for additional customization options.") + @available(visionOS, deprecated: 1, message: "Replaced by primaryActionForTextItem: and menuConfigurationForTextItem: for additional customization options.") public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { // If the delegate function is not set, return `true` to let the default interaction handle this return delegate?.headerFooterView?(self, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? true } -#endif // os(iOS) + + public func textView(_ textView: UITextView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? { + return delegate?.headerFooterView?(self, primaryActionFor: textItem, defaultAction: defaultAction) ?? defaultAction + } + + public func textView(_ textView: UITextView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? { + return delegate?.headerFooterView?(self, menuConfigurationFor: textItem, defaultMenu: defaultMenu) ?? .init(menu: defaultMenu) + } } // MARK: - TableViewHeaderFooterTitleView From 7e84fe4d6d84145bef7bf82015c7dd3ca8010498 Mon Sep 17 00:00:00 2001 From: Mike Schreiber Date: Fri, 30 Aug 2024 14:07:42 -0700 Subject: [PATCH 2/2] Include legacy implementation for iOS 16 --- .../Demos/TableViewHeaderFooterViewDemoController.swift | 9 +++++++++ ios/FluentUI/Table View/TableViewHeaderFooterView.swift | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift b/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift index 31d500fd0..06c7db58b 100644 --- a/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift +++ b/ios/FluentUI.Demo/FluentUI.Demo/Demos/TableViewHeaderFooterViewDemoController.swift @@ -164,6 +164,15 @@ extension TableViewHeaderFooterViewDemoController { // MARK: - TableViewHeaderFooterViewDemoController: TableViewHeaderFooterViewDelegate extension TableViewHeaderFooterViewDemoController: TableViewHeaderFooterViewDelegate { + @available (visionOS, deprecated: 1.0) + func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { + let alertController = UIAlertController(title: "Link tapped", message: nil, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + present(alertController, animated: true, completion: nil) + return false + } + + @available(iOS, introduced: 17) func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? { return UIAction { [weak self] _ in let alertController = UIAlertController(title: "Link tapped", message: nil, preferredStyle: .alert) diff --git a/ios/FluentUI/Table View/TableViewHeaderFooterView.swift b/ios/FluentUI/Table View/TableViewHeaderFooterView.swift index 8e76bcdc6..be240c7cf 100644 --- a/ios/FluentUI/Table View/TableViewHeaderFooterView.swift +++ b/ios/FluentUI/Table View/TableViewHeaderFooterView.swift @@ -22,6 +22,7 @@ public protocol TableViewHeaderFooterViewDelegate: AnyObject { /// @param defaultAction The default action for the text item. Return this to perform the default action. /// /// @return Return a UIAction to be performed when the text item is interacted with. Return @c nil to prevent the action from being performed. + @available(iOS, introduced: 17) @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? /// Asks the delegate for the menu configuration to be performed when interacting with a text item. @@ -31,7 +32,8 @@ public protocol TableViewHeaderFooterViewDelegate: AnyObject { /// @param defaultMenu The default menu for the specified text item. /// /// @return Return a menu configuration to be presented when the text item is interacted with. Return @c nil to prevent the menu from being presented. - @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? + @available(iOS, introduced: 17) + @objc optional func headerFooterView(_ headerFooterView: TableViewHeaderFooterView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? } // MARK: - TableViewHeaderFooterView @@ -575,10 +577,12 @@ extension TableViewHeaderFooterView: UITextViewDelegate { return delegate?.headerFooterView?(self, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? true } + @available(iOS, introduced: 17) public func textView(_ textView: UITextView, primaryActionFor textItem: UITextItem, defaultAction: UIAction) -> UIAction? { return delegate?.headerFooterView?(self, primaryActionFor: textItem, defaultAction: defaultAction) ?? defaultAction } + @available(iOS, introduced: 17) public func textView(_ textView: UITextView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? { return delegate?.headerFooterView?(self, menuConfigurationFor: textItem, defaultMenu: defaultMenu) ?? .init(menu: defaultMenu) }